diff --git a/controller/Controller.class.php b/controller/Controller.class.php index cb76a4d3..7ae3f310 100644 --- a/controller/Controller.class.php +++ b/controller/Controller.class.php @@ -89,9 +89,9 @@ class Controller $router->get(['/ios', 'get-ios'], 'DownloadActions::executeGet'); $router->get('/roadmap', 'ContentActions::executeRoadmap'); - $router->get('/developer-program', 'AcquisitionActions::executeDeveloperProgram'); - $router->post('/developer-program/post', 'AcquisitionActions::executeDeveloperProgramPost'); - $router->get('/developer-program/callback', 'AcquisitionActions::executeDeveloperProgramGithubCallback'); + $router->post('/quickstart/auth', 'DeveloperActions::executeQuickstartAuth'); + $router->get('/quickstart/{step}?', 'DeveloperActions::executeQuickstart'); + $router->get('/quickstart/github/callback', 'DeveloperActions::executeQuickstartGithubCallback'); $router->get(['/press-kit.zip', 'press-kit'], 'ContentActions::executePressKit'); @@ -127,7 +127,8 @@ class Controller '/deck.pdf' => 'https://www.dropbox.com/s/0xj4vgucsbi8rtv/lbry-deck.pdf?dl=1', '/pln.pdf' => 'https://www.dropbox.com/s/uevjrwnyr672clj/lbry-pln.pdf?dl=1', '/plan.pdf' => 'https://www.dropbox.com/s/uevjrwnyr672clj/lbry-pln.pdf?dl=1', - '/api-help' => 'https://lbryio.github.io/lbry/api/', + '/api' => 'https://lbryio.github.io/lbry', + '/api-help' => 'https://lbryio.github.io/lbry' ]; diff --git a/controller/Session.class.php b/controller/Session.class.php index 4291690f..fdb944d2 100644 --- a/controller/Session.class.php +++ b/controller/Session.class.php @@ -1,14 +1,16 @@ Session::get(Session::KEY_DEVELOPER_CREDITS_WALLET_ADDRESS), - 'error' => Session::getFlash(Session::KEY_DEVELOPER_CREDITS_ERROR), - 'success' => Session::getFlash(Session::KEY_DEVELOPER_CREDITS_SUCCESS) - ]]; - } - - public static function executeDeveloperProgramPost() - { - $walletAddress = trim(Request::getPostParam('wallet')); - Session::set(Session::KEY_DEVELOPER_CREDITS_WALLET_ADDRESS, $walletAddress); - - if (!$walletAddress) - { - Session::setFlash(Session::KEY_DEVELOPER_CREDITS_ERROR, 'Please provide a wallet address.'); - } - elseif (!preg_match('/^b[1-9A-HJ-NP-Za-km-z]{33}$/', $walletAddress)) - { - Session::setFlash(Session::KEY_DEVELOPER_CREDITS_ERROR, 'This does not appear to be a valid wallet address.'); - } - else - { - if (!Config::get('github_developer_credits_client_id')) - { - throw new Exception('no github client id'); - } - - $githubParams = [ - 'client_id' => Config::get('github_developer_credits_client_id'), - 'redirect_uri' => Request::getHostAndProto() . '/developer-program/callback', - 'scope' => 'user:email', - 'allow_signup' => false - ]; - return Controller::redirect('https://github.com/login/oauth/authorize?' . http_build_query($githubParams)); - } - return Controller::redirect('/developer-program'); - } - - public static function executeDeveloperProgramGithubCallback() - { - $code = Request::getParam('code'); - $walletAddress = Session::get(Session::KEY_DEVELOPER_CREDITS_WALLET_ADDRESS); - - if (!$walletAddress) - { - Session::setFlash(Session::KEY_DEVELOPER_CREDITS_ERROR, 'Your wallet address disappeared while authenticated with GitHub.'); - } - elseif (!$code) - { - Session::setFlash(Session::KEY_DEVELOPER_CREDITS_ERROR, 'This does not appear to be a valid response from GitHub.'); - } - else - { - $authResponseData = Curl::post('https://github.com/login/oauth/access_token', [ - 'code' => $code, - 'client_id' => Config::get('github_developer_credits_client_id'), - 'client_secret' => Config::get('github_developer_credits_client_secret') - ], [ - 'headers' => ['Accept: application/json'], - 'json_response' => true - ]); - - if (!$authResponseData || !isset($authResponseData['access_token'])) - { - Session::setFlash(Session::KEY_DEVELOPER_CREDITS_ERROR, 'Request to GitHub failed.'); - } - elseif (isset($authResponseData['error_description'])) - { - Session::setFlash(Session::KEY_DEVELOPER_CREDITS_ERROR, 'GitHub replied: ' . $authResponseData['error_description']); - } - else - { - $accessToken = $authResponseData['access_token']; - $userResponseData = Curl::get('https://api.github.com/user', [], [ - 'headers' => ['Authorization: token ' . $accessToken, 'Accept: application/json', 'User-Agent: lbryio'], - 'json_response' => true - ]); - - if (date('Y-m-d', strtotime($userResponseData['created_at'])) > '2017-01-30') - { - Session::setFlash(Session::KEY_DEVELOPER_CREDITS_ERROR, 'This GitHub account is too recent.'); - } - else - { - $lockName = 'github_dev_credits_write'; - $dataFile = ROOT_DIR . '/data/writeable/github_developer_credits'; - - $lock = Lock::getLock($lockName, true); // EXCLUSIVE LOCK. IF SENDING CREDITS IS SLOW, THIS COULD BLOCK USERS - - $existing = is_file($dataFile) ? json_decode(file_get_contents($dataFile), true) : []; - - if (isset($existing[$userResponseData['login']]) || isset($existing[$userResponseData['id']])) - { - Session::setFlash(Session::KEY_DEVELOPER_CREDITS_ERROR, 'You already received credits.'); - } - else - { - $response = - Curl::post('http://localhost:5279/lbryapi', [ - 'method' => 'send_amount_to_address', - 'params' => [['amount' => 250, 'address' => $walletAddress]], - ], [ - 'json_data' => true, - 'json_response' => true, - ]); - - if ($response === [true]) - { - $existing[$userResponseData['id']] = [$userResponseData['email'], $walletAddress, date('Y-m-d H:i:s'), $userResponseData['login']]; - file_put_contents($dataFile, json_encode($existing)); - - Session::setFlash(Session::KEY_DEVELOPER_CREDITS_SUCCESS, - 'Credits on their way to address ' . $walletAddress . ' for GitHub user ' . $userResponseData['login'] . '. It may take up to a minute for them to arrive.'); - } - else - { - if (isset($response['faultString']) && stripos($response['faultString'], 'InsufficientFundsError') !== false) - { - Slack::sendErrorIfProd('Github dev credits need a refill'); - Session::setFlash(Session::KEY_DEVELOPER_CREDITS_ERROR, - 'Our wallet is running low on funds. Please ping jeremy@lbry.io so he can refill it, then try again.'); - } - else - { - Slack::sendErrorIfProd('Error claiming github dev credits: ' . var_export($response, true)); - Session::setFlash(Session::KEY_DEVELOPER_CREDITS_ERROR, - 'Failed to send credits. This is an error on our side. Please email jeremy@lbry.io if it persists.'); - } - } - } - - Lock::freeLock($lock); - $lock = null; - } - } - } - return Controller::redirect('/developer-program'); - } } diff --git a/controller/action/DeveloperActions.class.php b/controller/action/DeveloperActions.class.php new file mode 100644 index 00000000..446d5ce3 --- /dev/null +++ b/controller/action/DeveloperActions.class.php @@ -0,0 +1,128 @@ + 'Home', + 'install' => 'Installation', + 'api' => 'The API', + 'credits' => 'Credits' + ]; + $allSteps = array_keys($stepLabels); + $currentStep = $step ?: $allSteps[0]; + + $viewParams = [ + 'currentStep' => $currentStep, + 'stepLabels' => $stepLabels + ]; + + if ($currentStep !== 'all') + { + if (!isset($stepLabels[$currentStep])) + { + Controller::redirect('/quickstart'); + } + + $stepNum = array_flip($allSteps)[$currentStep]; + + $viewParams += [ + 'stepNum' => $stepNum, + 'prevStep' => $stepNum === 0 ? null : $allSteps[$stepNum - 1], + 'nextStep' => $stepNum + 1 >= count($allSteps) ? null : $allSteps[$stepNum + 1], + ]; + } + + return ['developer/quickstart', $viewParams]; + } + + public static function prepareQuickstartHomePartial(array $vars) + { + return $vars + [ + 'usdValue' => static::DEVELOPER_REWARD * LBRY::getLBCtoUSDRate() + ]; + } + + public static function prepareFormNewDeveloperRewardPartial(array $vars) + { + return $vars + [ + 'defaultWalletAddress' => Session::get(Session::KEY_DEVELOPER_CREDITS_WALLET_ADDRESS), + 'error' => Session::get(Session::KEY_DEVELOPER_LAST_FORM) == "new_developer" ? Session::getFlash(Session::KEY_DEVELOPER_CREDITS_ERROR) : '', + 'apiUrl' => LBRY::getApiUrl('/user/new_github') + ]; + } + + public static function prepareFormCreditsPublishPartial(array $vars) + { + return $vars + [ + 'defaultWalletAddress' => Session::get(Session::KEY_DEVELOPER_CREDITS_WALLET_ADDRESS), + 'error' => Session::get(Session::KEY_DEVELOPER_LAST_FORM) == "new_publish" ? Session::getFlash(Session::KEY_DEVELOPER_CREDITS_ERROR) : '', + 'apiUrl' => LBRY::getApiUrl('/reward/new') + ]; + } + + public static function executeQuickstartAuth() + { + Session::set(Session::KEY_DEVELOPER_CREDITS_WALLET_ADDRESS, trim(Request::getPostParam('wallet_address'))); + Session::set(Session::KEY_DEVELOPER_LAST_FORM, Request::getPostParam('formName')); + + if (Request::getPostParam('returnUrl')) + { + Session::set(Session::KEY_DEVELOPER_RETURN_URL_SUCCESS, Request::getPostParam('returnUrl')); + } + + if (!Config::get('github_developer_credits_client_id')) + { + throw new Exception('no github client id'); + } + + $gitHubParams = [ + 'client_id' => Config::get('github_developer_credits_client_id'), + 'redirect_uri' => Request::getHostAndProto() . '/quickstart/github/callback', + 'scope' => 'user:email public_repo', + 'allow_signup' => false + ]; + + return Controller::redirect('https://github.com/login/oauth/authorize?' . http_build_query($gitHubParams)); + } + + public static function executeQuickstartGithubCallback() + { + $code = Request::getParam('code'); + + if (!$code) + { + Session::setFlash(Session::KEY_DEVELOPER_CREDITS_ERROR, 'This does not appear to be a valid response from GitHub.'); + } + else + { + $authResponseData = Curl::post('https://github.com/login/oauth/access_token', [ + 'code' => $code, + 'client_id' => Config::get('github_developer_credits_client_id'), + 'client_secret' => Config::get('github_developer_credits_client_secret') + ], [ + 'headers' => ['Accept: application/json'], + 'json_response' => true + ]); + + if (!$authResponseData || !isset($authResponseData['access_token'])) + { + Session::setFlash(Session::KEY_DEVELOPER_CREDITS_ERROR, 'Request to GitHub failed.'); + } + elseif (isset($authResponseData['error_description'])) + { + Session::setFlash(Session::KEY_DEVELOPER_CREDITS_ERROR, 'GitHub replied: ' . $authResponseData['error_description']); + } + else + { + Session::set(Session::KEY_GITHUB_ACCESS_TOKEN, $authResponseData['access_token']); + } + } + + return Controller::redirect(Session::get(Session::KEY_DEVELOPER_RETURN_URL_SUCCESS, '/quickstart/credits')); + } +} diff --git a/lib/thirdparty/LBRY.class.php b/lib/thirdparty/LBRY.class.php new file mode 100644 index 00000000..3caf74d3 --- /dev/null +++ b/lib/thirdparty/LBRY.class.php @@ -0,0 +1,19 @@ + 3600, //one hour + 'json_response' => true + ]); + return $response['data']['lbc_usd'] ?? 0; + } +} \ No newline at end of file diff --git a/lib/tools/Curl.class.php b/lib/tools/Curl.class.php index 8602a1b9..95efef12 100644 --- a/lib/tools/Curl.class.php +++ b/lib/tools/Curl.class.php @@ -69,8 +69,8 @@ class Curl $ch = curl_init(); -// curl_setopt($ch, CURLOPT_VERBOSE, true); -// curl_setopt($ch, CURLOPT_STDERR, fopen(sys_get_temp_dir().'/curl-debug-'.date('Ymd-His'), 'w+')); + curl_setopt($ch, CURLOPT_VERBOSE, true); + curl_setopt($ch, CURLOPT_STDERR, fopen(sys_get_temp_dir().'/curl-debug-'.date('Ymd-His'), 'w+')); if ($ch === false || $ch === null) { diff --git a/view/template/acquisition/developer-program.php b/view/template/acquisition/developer-program.php deleted file mode 100644 index 938dca35..00000000 --- a/view/template/acquisition/developer-program.php +++ /dev/null @@ -1,32 +0,0 @@ - - - - false, 'isAbsolute' => false]) ?> -
-
-

Developer Program

-
This program is being revamped and will be re-enabled by 2/23.
-

All developers with a GitHub account prior to January 31st, 2017 are eligible for free credits.

-

To claim your credits, enter a wallet address in the form below and authenticate with GitHub.

-

- We will store your GitHub username and email address, but nothing else. -

-
-

Receive Credits

- -
- -
- -
- -
- -
-
- -
-
-
- diff --git a/view/template/developer/_formCreditsPublish.php b/view/template/developer/_formCreditsPublish.php new file mode 100644 index 00000000..71236bd3 --- /dev/null +++ b/view/template/developer/_formCreditsPublish.php @@ -0,0 +1,28 @@ + +lbry.quickstartForm('#form-new-publish-reward', ""); + +
+

Publishing Reward

+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ + + + +
+
\ No newline at end of file diff --git a/view/template/developer/_formNewDeveloperReward.php b/view/template/developer/_formNewDeveloperReward.php new file mode 100644 index 00000000..184e5a54 --- /dev/null +++ b/view/template/developer/_formNewDeveloperReward.php @@ -0,0 +1,23 @@ + + lbry.quickstartForm('#form-new-developer-reward', ""); + +
+

Receive Credits

+
+
+
+ +
+ +
+
+
+ + + + +
+
We require a GitHub account to prevent abuse. This will record your email (no spam) and mark you as interested in the lbry repo. + No GitHub account? No problem! Join our Slack channel and post an introduction in #tech.
+
\ No newline at end of file diff --git a/view/template/developer/_quickstartApi.php b/view/template/developer/_quickstartApi.php new file mode 100644 index 00000000..f1782e72 --- /dev/null +++ b/view/template/developer/_quickstartApi.php @@ -0,0 +1,35 @@ +

The API

+

+ When running, the LBRY daemon provides a JSON-RPC server running at https://localhost:5279/lbryapi. +

+

+ It can be accessed by any utility capable of making HTTPS GET and POST requests, such as cURL or possibly your toaster. +

+

+ To verify the LBRY daemon is running correctly, let's try looking up a name: +

+$curl 'http://localhost:5279/lbryapi' --data '{"method":"resolve_name","params":{"name":"what"}}' +[ + { + "ver": "0.0.3", + "description": "What is LBRY? An introduction with Alex Tabarrok", + "license": "LBRY inc", + "title": "What is LBRY?", + "author": "Samuel Bryan", + "language": "en", + "sources": { + "lbry_sd_hash": "d5169241150022f996fa7cd6a9a1c421937276a3275eb912790bd07ba7aec1fac5fd45431d226b8fb402691e79aeb24b" + }, + "content_type": "video\/mp4", + "nsfw": false, + "thumbnail": "https:\/\/s3.amazonaws.com\/files.lbry.io\/logo.png" + } +] +

Above, we called the method resolve_name for the URL lbry://what. This returned the metadata associated with the URL.

+

Now let's download it. This time we're going to call the method get with the same parameters.

+$curl 'http://localhost:5279/lbryapi' --data '{"method":"get","params":{"name":"what"} }' +["d5169241150022f996fa7cd6a9a1c421937276a3275eb912790bd07ba7aec1fac5fd45431d226b8fb402691e79aeb24b"] +

The LBRY API consists about 50 calls, all related to discovering, distributing, and purchasing content. View the full API documentation.

+

You can also list all of the commands available by calling the help command.

+$curl 'http://localhost:5279/lbryapi' --data '{"method":"help"}' + \ No newline at end of file diff --git a/view/template/developer/_quickstartCredits.php b/view/template/developer/_quickstartCredits.php new file mode 100644 index 00000000..115f4667 --- /dev/null +++ b/view/template/developer/_quickstartCredits.php @@ -0,0 +1,47 @@ +

Credits

+

So far, everything we've done with LBRY has been free. However, some actions, such as reserving a name or purchasing paid content, require credits.

+

To receive credits, first generate a wallet address:

+$curl 'http://localhost:5279/lbryapi' --data '{"method":"wallet_new_address"}' +["bbFxRyWCFRkA9YcuuZD8nE7XTLUxYnddTs"] +

Enter this address in the form below and we'll send you 50 credits.

+
+ Request::getRelativeUri() . '#new-developer' + ]) ?> +
+

Next, confirm you've received your credits by calling wallet_balance:

+$curl 'http://localhost:5279/lbryapi' --data '{"method":"wallet_balance"}' +[50.00000000] +

Publishing

+
+ The credit reward for this portion of the guide does not work yet. It will be added shortly. However, you can still follow this section to learn how to publish. +
+

Publishing to LBRY is just as easy as everything else! If you publish something, we'll send you an additional 200 LBC for further use.

+

Not sure what to publish? We recommend your favorite picture or home video. Or just grab something from here.

+$curl 'http://localhost:5279/lbryapi' --data '{"method":"publish", "params": { + "name": "electricsheep", + "file_path": "\\home\kauffj\\Desktop\\electric-sheep.mp4", + "bid": 1, + "metadata": { } //this should match the metadata returned by resolve_name +}}' +[whatever this response looks like] +
+ Request::getRelativeUri() . '#new-developer' + ]) ?> +
+

Enjoy a Hollywood Film

+$curl 'http://localhost:5279/lbryapi' --data '{"method":"get","params":{"name":"itsadisaster"} }' +["d5169241150022f996fa7cd6a9a1c421937276a3275eb912790bd07ba7aec1fac5fd45431d226b8fb402691e79aeb24b"] +

Try the UI

+

LBRY comes with a UI so that normal people can use it too. You can download it here.

+

You Did It! What's Next?

+

+ Start building something awesome! LBRY works as a discovery and distribution backend for everything from films to CAD files. +

+

+ Join our Slack Channel to interact with LBRY developers and other community members. Please visit the #dev room (note: this is not a default channel). +

+

+ Visit our GitHub page to view the source code or report issues. +

\ No newline at end of file diff --git a/view/template/developer/_quickstartHome.php b/view/template/developer/_quickstartHome.php new file mode 100644 index 00000000..7821da47 --- /dev/null +++ b/view/template/developer/_quickstartHome.php @@ -0,0 +1,21 @@ +
Quickstart Home
+

+ LBRY is an open-source "fat" protocol, providing + decentralized content discovery and distribution.

+

+ In just a few minutes, you will have: +

+ +

+ Begin the Guide +

+
Not a guide lover? Here it is all on one page.
\ No newline at end of file diff --git a/view/template/developer/_quickstartInstall.php b/view/template/developer/_quickstartInstall.php new file mode 100644 index 00000000..a26baf1d --- /dev/null +++ b/view/template/developer/_quickstartInstall.php @@ -0,0 +1,33 @@ +

Download

+ + + + + + + + + + + + + + + +
macOS Linux Windows
Download .dmgDownload .debDownload .msi
+

+ If you prefer to compile from source or are not on one of the above operating systems, follow + this guide. +

+

Run

+

+ Launch the deamon to run as a background process: +

+

+ $lbrynet-daemon +

+

While running, the daemon will provide a JSON-RPC interface on localhost. We'll learn how to interact with that next.

+macOS and Windows do not currently bundle the daemon separately. Just launch the full app and the API will still be available. This will be resolved in v0.9. +
The first time you run the daemon, it must catch-up with most recent blockheaders. This can take a few minutes.
+ */ ?> \ No newline at end of file diff --git a/view/template/developer/quickstart.php b/view/template/developer/quickstart.php new file mode 100644 index 00000000..48d6d030 --- /dev/null +++ b/view/template/developer/quickstart.php @@ -0,0 +1,53 @@ + + + + + false, 'isAbsolute' => false]) ?> +
+
+
+ +
+ +

Quickstart

+
+ +
+
+ +
+
+ + 0): ?> +
+

Quickstart:

+
+
    + + $stepLabel): ?> +
  1. + +
  2. + +
+
+
+ +
+ +
+ Next: » +
+ +
+ +
+ array_keys($stepLabels)[1] + ]) ?> +
+ +
+
+
+ \ No newline at end of file diff --git a/view/template/layout/basic.php b/view/template/layout/basic.php index 6a6f254d..26064251 100644 --- a/view/template/layout/basic.php +++ b/view/template/layout/basic.php @@ -12,7 +12,7 @@ 'LBRY' ?> <?php echo $title ?> - + diff --git a/view/template/page/quickstart.php b/view/template/page/quickstart.php deleted file mode 100644 index db368513..00000000 --- a/view/template/page/quickstart.php +++ /dev/null @@ -1,135 +0,0 @@ - - - - false, 'isAbsolute' => false]) ?> -
-

Quickstart

-

This step-by-step guide will have you running LBRY and interacting with the API in just a few minutes.

-

This guide is for programmers and other technical users. For consumer usage of LBRY, please go here.

-

What's Covered

-
    -
  1. Installation
  2. -
  3. Running LBRY
  4. -
  5. The API
  6. -
  7. Credits
  8. -
  9. Community & Issues
  10. -
-
-

1. Installation

-

The easiest way to install LBRY is to use a pre-packaged binary. We provide binaries for Windows, macOS, and Debian-based Linux.

- - - - - - - - - - - - - - - -
macOS Linux Windows
Download DMGDownload DEBDownload MSI
-

- If you prefer to compile from source or are not on one of the above operating systems, follow - this guide. -

-
-
-

2. Running LBRY

-

- Launch the deamon to run as a background process: -

-

- $lbrynet-daemon -

-

The first time you run the daemon, it must catch-up with most recent blockheaders. This can take several minutes.

-
macOS and Windows do not currently bundle the daemon separately. Just launch the full app and the API will still be available. This will be resolved in v0.9.
-
-
-

3. The API

-

- When running, the LBRY daemon provides a JSON-RPC server running at https://localhost:5279/lbryapi. -

-

- It can be accessed via cURL or any other utility capable of making HTTPS GET and POST requests. -

-

- To verify the LBRY daemon is running correctly and responding to requests, run: -

- $curl 'http://localhost:5279/lbryapi' --data '{"method":"status","params":[]}' -[ - { - "connection_status": { - "message": "No connection problems detected", - "code": "connected" - }, - "is_first_run": false, - "is_running": true, - "blocks_behind": 0, - "startup_status": { - "message": "Started lbrynet", - "code": "started" - } - } -] -

This makes it easy to interact with the LBRY API in the programming language of your choice. Here's another example:

- $curl 'http://localhost:5279/lbryapi' --data '{"method":"resolve_name","params":[{"name":"what"}]}' -[ - { - "ver": "0.0.3", - "description": "What is LBRY? An introduction with Alex Tabarrok", - "license": "LBRY inc", - "title": "What is LBRY?", - "author": "Samuel Bryan", - "language": "en", - "sources": { - "lbry_sd_hash": "d5169241150022f996fa7cd6a9a1c421937276a3275eb912790bd07ba7aec1fac5fd45431d226b8fb402691e79aeb24b" - }, - "content_type": "video\/mp4", - "nsfw": false, - "thumbnail": "https:\/\/s3.amazonaws.com\/files.lbry.io\/logo.png" - } -] -

LBRY can be used to build everything from a censorship-proof image host, to a store for 3D printing files, to distribute large files or datasets, or use cases even we can't imagine!

-

View Full API Documentation

-
-
-

4. Getting Credits

-

Many actions, such as reserving a name or purchasing paid content, require credits.

-

To receive credits, first generate a wallet address:

- $curl 'http://localhost:5279/lbryapi' --data '{"method":"wallet_new_address","params":[]}' -["bbFxRyWCFRkA9YcuuZD8nE7XTLUxYnddTs"] -

Use this address to get credits in one of two ways:

-
-
-

4a) Receive Free Credits

-

- All developers with a valid GitHub account are eligible to receive free credits. -

- Claim Your Free Credits -
-
-

4b) Purchase Credits

-

- Credits can be bought on a variety of exchanges. - After purchasing, send them to the address generated above. -

-
-
-
-
-

5. Community & Issues

-

- Join our Slack Channel to interact with LBRY developers and other community members. Please visit the #dev room (note: this is not a default channel). -

-

- Visit our GitHub page to view the source code or report issues. -

-
- -
- diff --git a/view/template/page/what.php b/view/template/page/what.php index c707f4e8..724ade3c 100644 --- a/view/template/page/what.php +++ b/view/template/page/what.php @@ -96,16 +96,17 @@

Here is a sample key-value entry in the LBRY blockchain. Here, wonderfullife is the key, and the rest of the description is the value.

$lbrynet-cli resolve_name name=wonderfullife -wonderfullife : { - title: "It’s a Wonderful Life", - description: "An angel helps a compassionate but despairingly frustrated businessman by showing what life would have been like if he never existed.", - thumbnail: "http://i.imgur.com/MW45x88.jpg", - license: "public domain", - price: 0, //free! - publisher: "A Fan Of George Bailey", //simplification - sources: { //extensible, variable list - lbry_hash : <unique id>, - url : <url> + +wonderfullife : { + title: "It’s a Wonderful Life", + description: "An angel helps a compassionate but despairingly frustrated businessman by showing what life would have been like if he never existed.", + thumbnail: "http://i.imgur.com/MW45x88.jpg", + license: "public domain", + price: 0, //free! + publisher: "A Fan Of George Bailey", //simplification + sources: { //extensible, variable list + lbry_hash : <unique id>, + url : <url> } }

A slightly simplified sample entry of metadata in the LBRY blockchain. Whichever party or parties bid the most in an ongoing auction control what a name returns.

@@ -244,16 +245,16 @@

Here is a sample key-value entry in the LBRY blockchain. Here, wonderfullife is the key, and the rest of the description is the value.

-    wonderfullife : {
-      title: "It’s a Wonderful Life",
-      description: "An angel helps a compassionate but despairingly frustrated businessman by showing what life would have been like if he never existed.",
-      thumbnail: "http://i.imgur.com/MW45x88.jpg",
-      license: "public domain",
-      price: 0, //free!
-      publisher: "A Fan Of George Bailey", //simplification
-      sources: { //extensible, variable list
-        lbry_hash : <unique id>,
-        url : <url>
+    wonderfullife : {
+      title: "It’s a Wonderful Life",
+      description: "An angel helps a compassionate but despairingly frustrated businessman by showing what life would have been like if he never existed.",
+      thumbnail: "http://i.imgur.com/MW45x88.jpg",
+      license: "public domain",
+      price: 0, //free!
+      publisher: "A Fan Of George Bailey", //simplification
+      sources: { //extensible, variable list
+        lbry_hash : <unique id>,
+        url : <url>
       }
     }
diff --git a/view/template/social/_listDev.php b/view/template/social/_listDev.php index f31f83af..783b7887 100644 --- a/view/template/social/_listDev.php +++ b/view/template/social/_listDev.php @@ -3,6 +3,9 @@ Documentation */ ?> +
+ Quickstart +
{{social.github}}
diff --git a/web/img/lbry-white-logo-only.svg b/web/img/lbry-white-logo-only.svg new file mode 100644 index 00000000..9f2352f9 --- /dev/null +++ b/web/img/lbry-white-logo-only.svg @@ -0,0 +1,79 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/web/js/quickstart.js b/web/js/quickstart.js new file mode 100644 index 00000000..61d119f8 --- /dev/null +++ b/web/js/quickstart.js @@ -0,0 +1,82 @@ +lbry.quickstartForm = function (selector, apiUrl) { + var form = $(selector), + accessToken = form.find(':input[name="access_token"]').val(), + walletAddressInput = form.find(':input[name="wallet_address"]'), + transactionHashInput = form.find(':input[name="transaction_hash"]'), + storageKey = form.attr('id') + "SuccessHTML", + submitButton = form.find(':input[type="submit"]'), + isAutomaticSubmit = false, + isSubmitting = false; + + function resetFormState() { + isSubmitting = false; + walletAddressInput.attr('readonly', null); + transactionHashInput.attr('readonly', null); + submitButton.val(submitButton.data('submitLabel')).attr('disabled', null); + } + + if (window.localStorage.getItem(storageKey)) { + form.find('.notice-success').html(window.localStorage.getItem(storageKey)).show(); + form.find('.form-row, .submit-row').hide(); + } else if (accessToken) { + form.submit(function (event) { + if (isSubmitting) { + return false; + } + + var postData = { + access_token: accessToken, + wallet_address: walletAddressInput.val() + }; + + form.find('.notice-success, .notice-error').hide(); + + if (!walletAddressInput.val()) { + resetFormState(); + if (!isAutomaticSubmit) { + form.find('.notice-error').html("Please supply a wallet address.").show(); + } + return false; + } + + if (transactionHashInput.length) { + if (!transactionHashInput.val()) { + resetFormState(); + if (!isAutomaticSubmit) { + form.find('.notice-error').html("Please supply a transaction ID.").show(); + } + return false; + } + postData.transaction_hash = transactionHashInput.val(); + } + + event.preventDefault(); + + walletAddressInput.attr('readonly', 'readonly'); + transactionHashInput.attr('readonly', 'readonly'); + submitButton.val(submitButton.data('submittingLabel')).attr('disabled', 'disabled'); + + $.post(apiUrl, postData) + .done(function (responseData) { + var data = responseData.data; + var anchor = $(''); + anchor.attr("href", "https://explorer.lbry.io/tx/" + data.TransactionHash); + anchor.html(data.TransactionHash) + form.find('.notice-success') + .html(data.RewardAmount + " credits sent in transaction ") + .append(anchor) + .show(); + window.localStorage.setItem(storageKey, form.find('.notice-success').html()); + }) + .fail(function (xhr) { + var responseData = $.parseJSON(xhr.responseText); + form.find('.notice-error').html(responseData.error.length ? responseData.error : "Something went wrong. Please email grin@lbry.io").show(); + }) + .always(resetFormState); + }) + + isAutomaticSubmit = true; + form.submit(); + isAutomaticSubmit = false; + } +} \ No newline at end of file diff --git a/web/scss/_basic.scss b/web/scss/_basic.scss index b24881bd..73bcc505 100644 --- a/web/scss/_basic.scss +++ b/web/scss/_basic.scss @@ -82,6 +82,10 @@ section { @include anchor($color-primary); } +.link-primary--break-word +{ + word-break: break-all; +} a:hover img { opacity: 0.75; diff --git a/web/scss/_blog.scss b/web/scss/_blog.scss index cf2dc66d..f183d126 100644 --- a/web/scss/_blog.scss +++ b/web/scss/_blog.scss @@ -109,7 +109,7 @@ margin-top: $spacing-vertical; } } -.post-content table, table.content +.post-content table, table.post-content-table { margin-bottom: $spacing-vertical; word-wrap: break-word; @@ -135,7 +135,6 @@ font-size: 0.9em; padding: $spacing-vertical/4+1 8px $spacing-vertical/4-2; text-align: left; - border-bottom: 1px solid #e2e2e2; img { vertical-align: text-bottom; @@ -145,37 +144,11 @@ { vertical-align: middle; } - tr.thead:not(:first-child) th - { - border-top: 1px solid #e2e2e2; - } tfoot td { padding: $spacing-vertical / 2 8px; font-size: .85em; } - tbody - { - tr - { - &:nth-child(even):not(.odd) - { - background-color: #f4f4f4; - } - &:nth-child(odd):not(.even) - { - background-color: white; - } - &.thead - { - background: none; - } - td - { - border: 0 none; - } - } - } &:last-child { @@ -187,6 +160,39 @@ width: 100%; } } +.post-content table +{ + thead th, > tr:first-child th + { + border-bottom: 1px solid #e2e2e2; + } + tr.thead:not(:first-child) th + { + border-top: 1px solid #e2e2e2; + } + tbody + { + tr + { + &.thead + { + background: none; + } + td + { + border: 0 none; + } + &:nth-child(even):not(.odd) + { + background-color: #f4f4f4; + } + &:nth-child(odd):not(.even) + { + background-color: white; + } + } + } +} .post-author-spotlight { diff --git a/web/scss/_code.scss b/web/scss/_code.scss index a28c2197..fd046f77 100644 --- a/web/scss/_code.scss +++ b/web/scss/_code.scss @@ -7,8 +7,16 @@ pre, code code { padding: 3px 5px; - font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, monospace, serif; + font-family: $font-mono; color: darken($color-primary, 10%); + &.code-inline { + padding: 0; + margin-left: 1px; + margin-right: 1px; + font-weight: bold; + color: inherit; + background-color: transparent; + } } pre { @@ -30,7 +38,6 @@ pre user-select: text; margin-bottom: $spacing-vertical; - border-left: .3rem solid $color-primary; padding: $spacing-vertical / 2 $spacing-vertical; unicode-bidi: embed; overflow-x: auto; @@ -38,10 +45,22 @@ pre display: block; word-wrap: break-word; + background: #222; + color: #fff; + font-size: 0.75em; } -.code-bash__kw1 {color: #c20cb9; font-weight: bold;} -.code-bash__kw2 {color: #7a0874; font-weight: bold; } +.code-bash__response { + color: #ccc; +} + +.code-bash__kw {color: #c20cb9; font-weight: bold;} .code-bash__comment { color: #888; } -.code-bash__prompt { font-weight: bold; margin-right: 5px; } \ No newline at end of file +.code-bash__prompt +{ + font-weight: bold; + margin-right: 5px; + color: lighten($color-primary, 20%); + @include user-select(none); +} \ No newline at end of file diff --git a/web/scss/_content.scss b/web/scss/_content.scss index 2bf7c601..dbbeb68b 100644 --- a/web/scss/_content.scss +++ b/web/scss/_content.scss @@ -128,11 +128,6 @@ &:last-child { margin-bottom: $spacing-vertical / 2; } padding-left: 2em; counter-reset: li-counter; - &.table-of-contents > li - { - line-height: 2em; - &:before { top: -0.1em; } - } > li { position: relative; diff --git a/web/scss/_form.scss b/web/scss/_form.scss index 4754d778..2f3d4d4b 100644 --- a/web/scss/_form.scss +++ b/web/scss/_form.scss @@ -81,11 +81,6 @@ input[type="date"] { vertical-align: middle; } -input.input-wallet -{ - width: 400px; -} - textarea { height: auto; min-height: 60px; @@ -104,6 +99,9 @@ input[type="date"] { border: 1px solid #ccc; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); transition: all 0.2s linear; + &[readonly] { + background-color: #bbb; + } } textarea:focus, @@ -126,6 +124,9 @@ input[type="checkbox"] { width: auto; } +input[type="submit"][disabled] { + cursor: auto; +} .mail-submit, .invite-submit { diff --git a/web/scss/_global.scss b/web/scss/_global.scss index a19b3600..d3959b3c 100644 --- a/web/scss/_global.scss +++ b/web/scss/_global.scss @@ -20,6 +20,7 @@ $max-post-content-width: 800px; $font-header: 'Raleway', sans-serif; $font-body: 'Raleway', sans-serif; +$font-mono: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, monospace, serif; $font-size-h1: 2.4em; $font-size-h2: 2.0em; @@ -168,6 +169,13 @@ $info_text: #3a87ad; } +@mixin user-select ($value) { + -webkit-user-select: $value; + -moz-user-select: $value; + -ms-user-select: $value; + user-select: $value; +} + @mixin transition($transition-property, $transition-time, $method) { -webkit-transition: $transition-property $transition-time $method; -moz-transition: $transition-property $transition-time $method; diff --git a/web/scss/_quickstart.scss b/web/scss/_quickstart.scss new file mode 100644 index 00000000..d1214e47 --- /dev/null +++ b/web/scss/_quickstart.scss @@ -0,0 +1,107 @@ +@import "global"; + +.quickstart +{ + max-width: 860px; +} + +.quickstart .content-dark +{ + ul, ol, li + { + list-style-position: outside !important; /*hack fix for CSS bug affecting headers inside LI tags, ask Grin*/ + } +} + +.quickstart__table +{ + margin: 0 auto $spacing-vertical; + td, th + { + border-right: 1px dotted #eee; + padding: 4px 20px; + &:last-child + { + border-right: 0 none; + } + } +} + +.quickstart__section +{ + margin-bottom: $spacing-vertical * 3; +} + +.quickstart__claim-form +{ + margin: $spacing-vertical * 2 0; + input[type="text"] { width: 100%; } +} + +.quickstart__progress-bar +{ + margin: $spacing-vertical * 3 80px; + background: #ddd; + display: flex; + height: 16px; + list-style: none; + padding: 0; + position: relative; + + > li { + flex: auto; + list-style: none; + position: relative; + + &:first-child { + max-width: 0; + + > a { + // arbitrary values + // since % won't work + right: -30px; + width: 60px; + } + } + + &:before { + background: #ddd; + border-radius: 50%; + content: ""; + display: block; + height: 24px; + right: -12px; + position: absolute; + top: -4px; + width: 24px; + } + } + a { + cursor: pointer; + color: #ccc; + padding: 4px 0; + position: absolute; + right: -25%; + text-align: center; + text-decoration: underline; + top: -36px; + width: 50%; + } + $color-indicator: #777; + .completed { + background: lighten($color-indicator, 10%); + + &:before { + background: lighten($color-indicator, 10%); + } + } + .active { + a { font-weight: bold; } + background: lighten($color-indicator, 10%); + + &:before { + background: lighten($color-indicator, 16%); + box-shadow: 0 1px 1px rgba(0,0,0,0.3); + } + } +} \ No newline at end of file diff --git a/web/scss/all.scss b/web/scss/all.scss index f6020391..3efb75b5 100644 --- a/web/scss/all.scss +++ b/web/scss/all.scss @@ -15,4 +15,5 @@ @import "blog"; @import "bounty"; @import "roadmap"; +@import "quickstart"; @import "social"; \ No newline at end of file