From 08ba3a37d436e896685dbc939cf6844125d43aed Mon Sep 17 00:00:00 2001 From: "Carlos R. Mercado" <107061601+charlieflipside@users.noreply.github.com> Date: Thu, 19 Jan 2023 14:55:24 -0500 Subject: [PATCH] initiate --- .Rprofile | 1 + .gitignore | 5 + FLIPSIDE-BRAND-1-BLACK.png | Bin 0 -> 8815 bytes FLIPSIDE-BRAND-1-WHITE.png | Bin 0 -> 8177 bytes LICENSE | 21 + README.md | 51 ++ footer.html | 0 header.html | 3 + onchain-pricing.Rmd | 19 + onchain-pricing.Rproj | 13 + renv.lock | 392 +++++++++++++++ renv/.gitignore | 6 + renv/activate.R | 942 +++++++++++++++++++++++++++++++++++++ renv/settings.dcf | 10 + styles.css | 112 +++++ 15 files changed, 1575 insertions(+) create mode 100644 .Rprofile create mode 100644 .gitignore create mode 100644 FLIPSIDE-BRAND-1-BLACK.png create mode 100644 FLIPSIDE-BRAND-1-WHITE.png create mode 100644 LICENSE create mode 100644 README.md create mode 100644 footer.html create mode 100644 header.html create mode 100644 onchain-pricing.Rmd create mode 100644 onchain-pricing.Rproj create mode 100644 renv.lock create mode 100644 renv/.gitignore create mode 100644 renv/activate.R create mode 100644 renv/settings.dcf create mode 100644 styles.css diff --git a/.Rprofile b/.Rprofile new file mode 100644 index 0000000..81b960f --- /dev/null +++ b/.Rprofile @@ -0,0 +1 @@ +source("renv/activate.R") diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8f4d207 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.Rproj.user +.Rhistory +.RData +.Ruserdata +api_key.txt diff --git a/FLIPSIDE-BRAND-1-BLACK.png b/FLIPSIDE-BRAND-1-BLACK.png new file mode 100644 index 0000000000000000000000000000000000000000..c3f5fa1bf07349731b93f0f608f7537d7901fa2b GIT binary patch literal 8815 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 literal 0 HcmV?d00001 diff --git a/FLIPSIDE-BRAND-1-WHITE.png b/FLIPSIDE-BRAND-1-WHITE.png new file mode 100644 index 0000000000000000000000000000000000000000..984c2ba42e935f0027403bf9ca0981f30c17053c GIT binary patch literal 8177 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 literal 0 HcmV?d00001 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..cc73c82 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Carlos R. Mercado + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7934a63 --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +# Topic: Onchain-Pricing + +For any reproducible analysis using this template please follow the provided format. + +1. 2-3 sentence summary of the analysis. +2. Link to both the general research site & specific report on that research site. A markdown example is provided to show how to link using `[]()` syntax. Details on how to update the research site are available [at its repo](https://github.com/FlipsideCrypto/research). + +`For a deeper dive into the context, you can check out the report on our [research site](https://science.flipsidecrypto.xyz/research/) at [bonk-post-mortem](https://science.flipsidecrypto.xyz/bonk-post-mortem/).` + +3. Link to the email sized version of the analysis on the flipside beehiiv. A markdown example is provided showing how to use the `[]()` syntax and identify the beehiiv site. To add content to the beehiiv site, please contact the beehiiv admin to get added as an org member. + +`If you aren't interested in code and want the shortest summary of the situation, you can check out the email sized [bonk-post-mortem](https://flipsidecrypto.beehiiv.com/p/bonk-post-mortem) on our research beehiiv and subscribe to get (summaries of) the best crypto research direct to your inbox.` + +4. Keep the Reproduce Analysis section (confirm links work) with the shroomDK and renv subheaders. Confirm your analysis is reproducible by using renv and that any SQL code you used to pull data is provided and accessible via shroomDK. For Python analysis use `pyenv` and `pip install shroomdk` and swap out any R details for Python ones. + +5. Update the instructions section. + +- To keep code bases uniform, please use `readLines('api_key.txt')` to access your api key within code and ensure gitignore files are consistently able to keep API Keys off github. + +- Use R Projects & renv to ensure portability across directories and operating systems. + +- For analysis across multiple files; either provide a single .Rmd file that accesses those files in order or explicitly detail what order .R files should be run in. + +# Reproduce Analysis + +All analysis is reproducible using the R programming language. You'll need (1) an shroomDK API key to copy our SQL queries and extract data from the [FlipsideCrypto data app](https://next.flipsidecrypto.xyz/); and (2) renv to get the exact package versions we used. + +## shroomDK + +shroomDK is an R package that accesses the FlipsideCrypto REST API; it is also available for Python. You pass SQL code as a string to our API and get up to 1M rows of data back! + +Check out the [documentation](https://docs.flipsidecrypto.com/shroomdk-sdk/get-started) and get your free API Key today. + +## renv + +renv is a package manager for the R programming language. It ensures analysis is fully reproducible by tracking the exact package versions used in the analysis. + +`install.packages('renv')` + +## Instructions + +To replicate this analysis please do the following: + +1. Clone this repo. +2. Save your API key into a .txt file as 'api_key.txt' (this exact naming allows the provided .gitignore to ignore your key and keep it off github). +3. Open the `R PROJECT NAME HERE` R Project file in your R IDE (we recommend, RStudio). +4. Confirm you have renv installed. +5. Restore the R environment using `renv::restore()` while in the `R PROJECT NAME HERE` R Project. +6. You can now run `SPECIFY .R FILE(s) and/or .Rmd FILE(s) HERE` + +If any errors arise, double check you have saved your API key in the expected file name and format. diff --git a/footer.html b/footer.html new file mode 100644 index 0000000..e69de29 diff --git a/header.html b/header.html new file mode 100644 index 0000000..3ad4b7a --- /dev/null +++ b/header.html @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/onchain-pricing.Rmd b/onchain-pricing.Rmd new file mode 100644 index 0000000..5057d00 --- /dev/null +++ b/onchain-pricing.Rmd @@ -0,0 +1,19 @@ +--- +title: "On-Chain Pricing" +author: "Charliemarketplace" +date: "`r Sys.Date()`" +output: + html_document: + css: "styles.css" + includes: + in_header: header.html + code_folding: hide + toc: true + toc_float: true +editor_options: + chunk_output_type: console +--- + +FlipsideCrypto's Research is open source. Check out all the code for this report [here](https://github.com/FlipsideCrypto/onchain-pricing) on github. + +# Intro diff --git a/onchain-pricing.Rproj b/onchain-pricing.Rproj new file mode 100644 index 0000000..8e3c2eb --- /dev/null +++ b/onchain-pricing.Rproj @@ -0,0 +1,13 @@ +Version: 1.0 + +RestoreWorkspace: Default +SaveWorkspace: Default +AlwaysSaveHistory: Default + +EnableCodeIndexing: Yes +UseSpacesForTab: Yes +NumSpacesForTab: 2 +Encoding: UTF-8 + +RnwWeave: Sweave +LaTeX: pdfLaTeX diff --git a/renv.lock b/renv.lock new file mode 100644 index 0000000..675c7c1 --- /dev/null +++ b/renv.lock @@ -0,0 +1,392 @@ +{ + "R": { + "Version": "4.2.1", + "Repositories": [ + { + "Name": "CRAN", + "URL": "https://cran.rstudio.com" + } + ] + }, + "Packages": { + "R6": { + "Package": "R6", + "Version": "2.5.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "470851b6d5d0ac559e9d01bb352b4021", + "Requirements": [] + }, + "askpass": { + "Package": "askpass", + "Version": "1.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "e8a22846fff485f0be3770c2da758713", + "Requirements": [ + "sys" + ] + }, + "base64enc": { + "Package": "base64enc", + "Version": "0.1-3", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "543776ae6848fde2f48ff3816d0628bc", + "Requirements": [] + }, + "bslib": { + "Package": "bslib", + "Version": "0.4.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "a7fbf03946ad741129dc81098722fca1", + "Requirements": [ + "base64enc", + "cachem", + "htmltools", + "jquerylib", + "jsonlite", + "memoise", + "mime", + "rlang", + "sass" + ] + }, + "cachem": { + "Package": "cachem", + "Version": "1.0.6", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "648c5b3d71e6a37e3043617489a0a0e9", + "Requirements": [ + "fastmap", + "rlang" + ] + }, + "cli": { + "Package": "cli", + "Version": "3.6.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "3177a5a16c243adc199ba33117bd9657", + "Requirements": [] + }, + "curl": { + "Package": "curl", + "Version": "5.0.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "e4f97056611e8e6b8b852d13b7400cf1", + "Requirements": [] + }, + "digest": { + "Package": "digest", + "Version": "0.6.31", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "8b708f296afd9ae69f450f9640be8990", + "Requirements": [] + }, + "ellipsis": { + "Package": "ellipsis", + "Version": "0.3.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "bb0eec2fe32e88d9e2836c2f73ea2077", + "Requirements": [ + "rlang" + ] + }, + "evaluate": { + "Package": "evaluate", + "Version": "0.20", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "4b68aa51edd89a0e044a66e75ae3cc6c", + "Requirements": [] + }, + "fastmap": { + "Package": "fastmap", + "Version": "1.1.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "77bd60a6157420d4ffa93b27cf6a58b8", + "Requirements": [] + }, + "fs": { + "Package": "fs", + "Version": "1.5.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "7c89603d81793f0d5486d91ab1fc6f1d", + "Requirements": [] + }, + "glue": { + "Package": "glue", + "Version": "1.6.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "4f2596dfb05dac67b9dc558e5c6fba2e", + "Requirements": [] + }, + "highr": { + "Package": "highr", + "Version": "0.10", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "06230136b2d2b9ba5805e1963fa6e890", + "Requirements": [ + "xfun" + ] + }, + "htmltools": { + "Package": "htmltools", + "Version": "0.5.4", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "9d27e99cc90bd701c0a7a63e5923f9b7", + "Requirements": [ + "base64enc", + "digest", + "ellipsis", + "fastmap", + "rlang" + ] + }, + "httr": { + "Package": "httr", + "Version": "1.4.4", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "57557fac46471f0dbbf44705cc6a5c8c", + "Requirements": [ + "R6", + "curl", + "jsonlite", + "mime", + "openssl" + ] + }, + "jquerylib": { + "Package": "jquerylib", + "Version": "0.1.4", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "5aab57a3bd297eee1c1d862735972182", + "Requirements": [ + "htmltools" + ] + }, + "jsonlite": { + "Package": "jsonlite", + "Version": "1.8.4", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "a4269a09a9b865579b2635c77e572374", + "Requirements": [] + }, + "knitr": { + "Package": "knitr", + "Version": "1.41", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "6d4971f3610e75220534a1befe81bc92", + "Requirements": [ + "evaluate", + "highr", + "stringr", + "xfun", + "yaml" + ] + }, + "lifecycle": { + "Package": "lifecycle", + "Version": "1.0.3", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "001cecbeac1cff9301bdc3775ee46a86", + "Requirements": [ + "cli", + "glue", + "rlang" + ] + }, + "magrittr": { + "Package": "magrittr", + "Version": "2.0.3", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "7ce2733a9826b3aeb1775d56fd305472", + "Requirements": [] + }, + "memoise": { + "Package": "memoise", + "Version": "2.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "e2817ccf4a065c5d9d7f2cfbe7c1d78c", + "Requirements": [ + "cachem", + "rlang" + ] + }, + "mime": { + "Package": "mime", + "Version": "0.12", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "18e9c28c1d3ca1560ce30658b22ce104", + "Requirements": [] + }, + "openssl": { + "Package": "openssl", + "Version": "2.0.5", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "b04c27110bf367b4daa93f34f3d58e75", + "Requirements": [ + "askpass" + ] + }, + "rappdirs": { + "Package": "rappdirs", + "Version": "0.3.3", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "5e3c5dc0b071b21fa128676560dbe94d", + "Requirements": [] + }, + "renv": { + "Package": "renv", + "Version": "0.15.5", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "6a38294e7d12f5d8e656b08c5bd8ae34", + "Requirements": [] + }, + "rlang": { + "Package": "rlang", + "Version": "1.0.6", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "4ed1f8336c8d52c3e750adcdc57228a7", + "Requirements": [] + }, + "rmarkdown": { + "Package": "rmarkdown", + "Version": "2.19", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "4e29299e1f4c7eabb0b8365b338adf3c", + "Requirements": [ + "bslib", + "evaluate", + "htmltools", + "jquerylib", + "jsonlite", + "knitr", + "stringr", + "tinytex", + "xfun", + "yaml" + ] + }, + "sass": { + "Package": "sass", + "Version": "0.4.4", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "c76cbac7ca04ce82d8c38e29729987a3", + "Requirements": [ + "R6", + "fs", + "htmltools", + "rappdirs", + "rlang" + ] + }, + "shroomDK": { + "Package": "shroomDK", + "Version": "0.1.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "28b8ac7aa1d889d635c3ac3c5150b11a", + "Requirements": [ + "httr", + "jsonlite" + ] + }, + "stringi": { + "Package": "stringi", + "Version": "1.7.12", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "ca8bd84263c77310739d2cf64d84d7c9", + "Requirements": [] + }, + "stringr": { + "Package": "stringr", + "Version": "1.5.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "671a4d384ae9d32fc47a14e98bfa3dc8", + "Requirements": [ + "cli", + "glue", + "lifecycle", + "magrittr", + "rlang", + "stringi", + "vctrs" + ] + }, + "sys": { + "Package": "sys", + "Version": "3.4.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "34c16f1ef796057bfa06d3f4ff818a5d", + "Requirements": [] + }, + "tinytex": { + "Package": "tinytex", + "Version": "0.43", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "facc02f3d63ed7dd765513c004c394ce", + "Requirements": [ + "xfun" + ] + }, + "vctrs": { + "Package": "vctrs", + "Version": "0.5.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "970324f6572b4fd81db507b5d4062cb0", + "Requirements": [ + "cli", + "glue", + "lifecycle", + "rlang" + ] + }, + "xfun": { + "Package": "xfun", + "Version": "0.36", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "f5baec54606751aa53ac9c0e05848ed6", + "Requirements": [] + }, + "yaml": { + "Package": "yaml", + "Version": "2.3.6", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "9b570515751dcbae610f29885e025b41", + "Requirements": [] + } + } +} diff --git a/renv/.gitignore b/renv/.gitignore new file mode 100644 index 0000000..275e4ca --- /dev/null +++ b/renv/.gitignore @@ -0,0 +1,6 @@ +library/ +local/ +cellar/ +lock/ +python/ +staging/ diff --git a/renv/activate.R b/renv/activate.R new file mode 100644 index 0000000..72c0818 --- /dev/null +++ b/renv/activate.R @@ -0,0 +1,942 @@ + +local({ + + # the requested version of renv + version <- "0.15.5" + + # the project directory + project <- getwd() + + # figure out whether the autoloader is enabled + enabled <- local({ + + # first, check config option + override <- getOption("renv.config.autoloader.enabled") + if (!is.null(override)) + return(override) + + # next, check environment variables + # TODO: prefer using the configuration one in the future + envvars <- c( + "RENV_CONFIG_AUTOLOADER_ENABLED", + "RENV_AUTOLOADER_ENABLED", + "RENV_ACTIVATE_PROJECT" + ) + + for (envvar in envvars) { + envval <- Sys.getenv(envvar, unset = NA) + if (!is.na(envval)) + return(tolower(envval) %in% c("true", "t", "1")) + } + + # enable by default + TRUE + + }) + + if (!enabled) + return(FALSE) + + # avoid recursion + if (identical(getOption("renv.autoloader.running"), TRUE)) { + warning("ignoring recursive attempt to run renv autoloader") + return(invisible(TRUE)) + } + + # signal that we're loading renv during R startup + options(renv.autoloader.running = TRUE) + on.exit(options(renv.autoloader.running = NULL), add = TRUE) + + # signal that we've consented to use renv + options(renv.consent = TRUE) + + # load the 'utils' package eagerly -- this ensures that renv shims, which + # mask 'utils' packages, will come first on the search path + library(utils, lib.loc = .Library) + + # unload renv if it's already been loaded + if ("renv" %in% loadedNamespaces()) + unloadNamespace("renv") + + # load bootstrap tools + `%||%` <- function(x, y) { + if (is.environment(x) || length(x)) x else y + } + + bootstrap <- function(version, library) { + + # attempt to download renv + tarball <- tryCatch(renv_bootstrap_download(version), error = identity) + if (inherits(tarball, "error")) + stop("failed to download renv ", version) + + # now attempt to install + status <- tryCatch(renv_bootstrap_install(version, tarball, library), error = identity) + if (inherits(status, "error")) + stop("failed to install renv ", version) + + } + + renv_bootstrap_tests_running <- function() { + getOption("renv.tests.running", default = FALSE) + } + + renv_bootstrap_repos <- function() { + + # check for repos override + repos <- Sys.getenv("RENV_CONFIG_REPOS_OVERRIDE", unset = NA) + if (!is.na(repos)) + return(repos) + + # check for lockfile repositories + repos <- tryCatch(renv_bootstrap_repos_lockfile(), error = identity) + if (!inherits(repos, "error") && length(repos)) + return(repos) + + # if we're testing, re-use the test repositories + if (renv_bootstrap_tests_running()) + return(getOption("renv.tests.repos")) + + # retrieve current repos + repos <- getOption("repos") + + # ensure @CRAN@ entries are resolved + repos[repos == "@CRAN@"] <- getOption( + "renv.repos.cran", + "https://cloud.r-project.org" + ) + + # add in renv.bootstrap.repos if set + default <- c(FALLBACK = "https://cloud.r-project.org") + extra <- getOption("renv.bootstrap.repos", default = default) + repos <- c(repos, extra) + + # remove duplicates that might've snuck in + dupes <- duplicated(repos) | duplicated(names(repos)) + repos[!dupes] + + } + + renv_bootstrap_repos_lockfile <- function() { + + lockpath <- Sys.getenv("RENV_PATHS_LOCKFILE", unset = "renv.lock") + if (!file.exists(lockpath)) + return(NULL) + + lockfile <- tryCatch(renv_json_read(lockpath), error = identity) + if (inherits(lockfile, "error")) { + warning(lockfile) + return(NULL) + } + + repos <- lockfile$R$Repositories + if (length(repos) == 0) + return(NULL) + + keys <- vapply(repos, `[[`, "Name", FUN.VALUE = character(1)) + vals <- vapply(repos, `[[`, "URL", FUN.VALUE = character(1)) + names(vals) <- keys + + return(vals) + + } + + renv_bootstrap_download <- function(version) { + + # if the renv version number has 4 components, assume it must + # be retrieved via github + nv <- numeric_version(version) + components <- unclass(nv)[[1]] + + # if this appears to be a development version of 'renv', we'll + # try to restore from github + dev <- length(components) == 4L + + # begin collecting different methods for finding renv + methods <- c( + renv_bootstrap_download_tarball, + if (dev) + renv_bootstrap_download_github + else c( + renv_bootstrap_download_cran_latest, + renv_bootstrap_download_cran_archive + ) + ) + + for (method in methods) { + path <- tryCatch(method(version), error = identity) + if (is.character(path) && file.exists(path)) + return(path) + } + + stop("failed to download renv ", version) + + } + + renv_bootstrap_download_impl <- function(url, destfile) { + + mode <- "wb" + + # https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17715 + fixup <- + Sys.info()[["sysname"]] == "Windows" && + substring(url, 1L, 5L) == "file:" + + if (fixup) + mode <- "w+b" + + utils::download.file( + url = url, + destfile = destfile, + mode = mode, + quiet = TRUE + ) + + } + + renv_bootstrap_download_cran_latest <- function(version) { + + spec <- renv_bootstrap_download_cran_latest_find(version) + + message("* Downloading renv ", version, " ... ", appendLF = FALSE) + + type <- spec$type + repos <- spec$repos + + info <- tryCatch( + utils::download.packages( + pkgs = "renv", + destdir = tempdir(), + repos = repos, + type = type, + quiet = TRUE + ), + condition = identity + ) + + if (inherits(info, "condition")) { + message("FAILED") + return(FALSE) + } + + # report success and return + message("OK (downloaded ", type, ")") + info[1, 2] + + } + + renv_bootstrap_download_cran_latest_find <- function(version) { + + # check whether binaries are supported on this system + binary <- + getOption("renv.bootstrap.binary", default = TRUE) && + !identical(.Platform$pkgType, "source") && + !identical(getOption("pkgType"), "source") && + Sys.info()[["sysname"]] %in% c("Darwin", "Windows") + + types <- c(if (binary) "binary", "source") + + # iterate over types + repositories + for (type in types) { + for (repos in renv_bootstrap_repos()) { + + # retrieve package database + db <- tryCatch( + as.data.frame( + utils::available.packages(type = type, repos = repos), + stringsAsFactors = FALSE + ), + error = identity + ) + + if (inherits(db, "error")) + next + + # check for compatible entry + entry <- db[db$Package %in% "renv" & db$Version %in% version, ] + if (nrow(entry) == 0) + next + + # found it; return spec to caller + spec <- list(entry = entry, type = type, repos = repos) + return(spec) + + } + } + + # if we got here, we failed to find renv + fmt <- "renv %s is not available from your declared package repositories" + stop(sprintf(fmt, version)) + + } + + renv_bootstrap_download_cran_archive <- function(version) { + + name <- sprintf("renv_%s.tar.gz", version) + repos <- renv_bootstrap_repos() + urls <- file.path(repos, "src/contrib/Archive/renv", name) + destfile <- file.path(tempdir(), name) + + message("* Downloading renv ", version, " ... ", appendLF = FALSE) + + for (url in urls) { + + status <- tryCatch( + renv_bootstrap_download_impl(url, destfile), + condition = identity + ) + + if (identical(status, 0L)) { + message("OK") + return(destfile) + } + + } + + message("FAILED") + return(FALSE) + + } + + renv_bootstrap_download_tarball <- function(version) { + + # if the user has provided the path to a tarball via + # an environment variable, then use it + tarball <- Sys.getenv("RENV_BOOTSTRAP_TARBALL", unset = NA) + if (is.na(tarball)) + return() + + # allow directories + info <- file.info(tarball, extra_cols = FALSE) + if (identical(info$isdir, TRUE)) { + name <- sprintf("renv_%s.tar.gz", version) + tarball <- file.path(tarball, name) + } + + # bail if it doesn't exist + if (!file.exists(tarball)) { + + # let the user know we weren't able to honour their request + fmt <- "* RENV_BOOTSTRAP_TARBALL is set (%s) but does not exist." + msg <- sprintf(fmt, tarball) + warning(msg) + + # bail + return() + + } + + fmt <- "* Bootstrapping with tarball at path '%s'." + msg <- sprintf(fmt, tarball) + message(msg) + + tarball + + } + + renv_bootstrap_download_github <- function(version) { + + enabled <- Sys.getenv("RENV_BOOTSTRAP_FROM_GITHUB", unset = "TRUE") + if (!identical(enabled, "TRUE")) + return(FALSE) + + # prepare download options + pat <- Sys.getenv("GITHUB_PAT") + if (nzchar(Sys.which("curl")) && nzchar(pat)) { + fmt <- "--location --fail --header \"Authorization: token %s\"" + extra <- sprintf(fmt, pat) + saved <- options("download.file.method", "download.file.extra") + options(download.file.method = "curl", download.file.extra = extra) + on.exit(do.call(base::options, saved), add = TRUE) + } else if (nzchar(Sys.which("wget")) && nzchar(pat)) { + fmt <- "--header=\"Authorization: token %s\"" + extra <- sprintf(fmt, pat) + saved <- options("download.file.method", "download.file.extra") + options(download.file.method = "wget", download.file.extra = extra) + on.exit(do.call(base::options, saved), add = TRUE) + } + + message("* Downloading renv ", version, " from GitHub ... ", appendLF = FALSE) + + url <- file.path("https://api.github.com/repos/rstudio/renv/tarball", version) + name <- sprintf("renv_%s.tar.gz", version) + destfile <- file.path(tempdir(), name) + + status <- tryCatch( + renv_bootstrap_download_impl(url, destfile), + condition = identity + ) + + if (!identical(status, 0L)) { + message("FAILED") + return(FALSE) + } + + message("OK") + return(destfile) + + } + + renv_bootstrap_install <- function(version, tarball, library) { + + # attempt to install it into project library + message("* Installing renv ", version, " ... ", appendLF = FALSE) + dir.create(library, showWarnings = FALSE, recursive = TRUE) + + # invoke using system2 so we can capture and report output + bin <- R.home("bin") + exe <- if (Sys.info()[["sysname"]] == "Windows") "R.exe" else "R" + r <- file.path(bin, exe) + + args <- c( + "--vanilla", "CMD", "INSTALL", "--no-multiarch", + "-l", shQuote(path.expand(library)), + shQuote(path.expand(tarball)) + ) + + output <- system2(r, args, stdout = TRUE, stderr = TRUE) + message("Done!") + + # check for successful install + status <- attr(output, "status") + if (is.numeric(status) && !identical(status, 0L)) { + header <- "Error installing renv:" + lines <- paste(rep.int("=", nchar(header)), collapse = "") + text <- c(header, lines, output) + writeLines(text, con = stderr()) + } + + status + + } + + renv_bootstrap_platform_prefix <- function() { + + # construct version prefix + version <- paste(R.version$major, R.version$minor, sep = ".") + prefix <- paste("R", numeric_version(version)[1, 1:2], sep = "-") + + # include SVN revision for development versions of R + # (to avoid sharing platform-specific artefacts with released versions of R) + devel <- + identical(R.version[["status"]], "Under development (unstable)") || + identical(R.version[["nickname"]], "Unsuffered Consequences") + + if (devel) + prefix <- paste(prefix, R.version[["svn rev"]], sep = "-r") + + # build list of path components + components <- c(prefix, R.version$platform) + + # include prefix if provided by user + prefix <- renv_bootstrap_platform_prefix_impl() + if (!is.na(prefix) && nzchar(prefix)) + components <- c(prefix, components) + + # build prefix + paste(components, collapse = "/") + + } + + renv_bootstrap_platform_prefix_impl <- function() { + + # if an explicit prefix has been supplied, use it + prefix <- Sys.getenv("RENV_PATHS_PREFIX", unset = NA) + if (!is.na(prefix)) + return(prefix) + + # if the user has requested an automatic prefix, generate it + auto <- Sys.getenv("RENV_PATHS_PREFIX_AUTO", unset = NA) + if (auto %in% c("TRUE", "True", "true", "1")) + return(renv_bootstrap_platform_prefix_auto()) + + # empty string on failure + "" + + } + + renv_bootstrap_platform_prefix_auto <- function() { + + prefix <- tryCatch(renv_bootstrap_platform_os(), error = identity) + if (inherits(prefix, "error") || prefix %in% "unknown") { + + msg <- paste( + "failed to infer current operating system", + "please file a bug report at https://github.com/rstudio/renv/issues", + sep = "; " + ) + + warning(msg) + + } + + prefix + + } + + renv_bootstrap_platform_os <- function() { + + sysinfo <- Sys.info() + sysname <- sysinfo[["sysname"]] + + # handle Windows + macOS up front + if (sysname == "Windows") + return("windows") + else if (sysname == "Darwin") + return("macos") + + # check for os-release files + for (file in c("/etc/os-release", "/usr/lib/os-release")) + if (file.exists(file)) + return(renv_bootstrap_platform_os_via_os_release(file, sysinfo)) + + # check for redhat-release files + if (file.exists("/etc/redhat-release")) + return(renv_bootstrap_platform_os_via_redhat_release()) + + "unknown" + + } + + renv_bootstrap_platform_os_via_os_release <- function(file, sysinfo) { + + # read /etc/os-release + release <- utils::read.table( + file = file, + sep = "=", + quote = c("\"", "'"), + col.names = c("Key", "Value"), + comment.char = "#", + stringsAsFactors = FALSE + ) + + vars <- as.list(release$Value) + names(vars) <- release$Key + + # get os name + os <- tolower(sysinfo[["sysname"]]) + + # read id + id <- "unknown" + for (field in c("ID", "ID_LIKE")) { + if (field %in% names(vars) && nzchar(vars[[field]])) { + id <- vars[[field]] + break + } + } + + # read version + version <- "unknown" + for (field in c("UBUNTU_CODENAME", "VERSION_CODENAME", "VERSION_ID", "BUILD_ID")) { + if (field %in% names(vars) && nzchar(vars[[field]])) { + version <- vars[[field]] + break + } + } + + # join together + paste(c(os, id, version), collapse = "-") + + } + + renv_bootstrap_platform_os_via_redhat_release <- function() { + + # read /etc/redhat-release + contents <- readLines("/etc/redhat-release", warn = FALSE) + + # infer id + id <- if (grepl("centos", contents, ignore.case = TRUE)) + "centos" + else if (grepl("redhat", contents, ignore.case = TRUE)) + "redhat" + else + "unknown" + + # try to find a version component (very hacky) + version <- "unknown" + + parts <- strsplit(contents, "[[:space:]]")[[1L]] + for (part in parts) { + + nv <- tryCatch(numeric_version(part), error = identity) + if (inherits(nv, "error")) + next + + version <- nv[1, 1] + break + + } + + paste(c("linux", id, version), collapse = "-") + + } + + renv_bootstrap_library_root_name <- function(project) { + + # use project name as-is if requested + asis <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT_ASIS", unset = "FALSE") + if (asis) + return(basename(project)) + + # otherwise, disambiguate based on project's path + id <- substring(renv_bootstrap_hash_text(project), 1L, 8L) + paste(basename(project), id, sep = "-") + + } + + renv_bootstrap_library_root <- function(project) { + + prefix <- renv_bootstrap_profile_prefix() + + path <- Sys.getenv("RENV_PATHS_LIBRARY", unset = NA) + if (!is.na(path)) + return(paste(c(path, prefix), collapse = "/")) + + path <- renv_bootstrap_library_root_impl(project) + if (!is.null(path)) { + name <- renv_bootstrap_library_root_name(project) + return(paste(c(path, prefix, name), collapse = "/")) + } + + renv_bootstrap_paths_renv("library", project = project) + + } + + renv_bootstrap_library_root_impl <- function(project) { + + root <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT", unset = NA) + if (!is.na(root)) + return(root) + + type <- renv_bootstrap_project_type(project) + if (identical(type, "package")) { + userdir <- renv_bootstrap_user_dir() + return(file.path(userdir, "library")) + } + + } + + renv_bootstrap_validate_version <- function(version) { + + loadedversion <- utils::packageDescription("renv", fields = "Version") + if (version == loadedversion) + return(TRUE) + + # assume four-component versions are from GitHub; three-component + # versions are from CRAN + components <- strsplit(loadedversion, "[.-]")[[1]] + remote <- if (length(components) == 4L) + paste("rstudio/renv", loadedversion, sep = "@") + else + paste("renv", loadedversion, sep = "@") + + fmt <- paste( + "renv %1$s was loaded from project library, but this project is configured to use renv %2$s.", + "Use `renv::record(\"%3$s\")` to record renv %1$s in the lockfile.", + "Use `renv::restore(packages = \"renv\")` to install renv %2$s into the project library.", + sep = "\n" + ) + + msg <- sprintf(fmt, loadedversion, version, remote) + warning(msg, call. = FALSE) + + FALSE + + } + + renv_bootstrap_hash_text <- function(text) { + + hashfile <- tempfile("renv-hash-") + on.exit(unlink(hashfile), add = TRUE) + + writeLines(text, con = hashfile) + tools::md5sum(hashfile) + + } + + renv_bootstrap_load <- function(project, libpath, version) { + + # try to load renv from the project library + if (!requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) + return(FALSE) + + # warn if the version of renv loaded does not match + renv_bootstrap_validate_version(version) + + # load the project + renv::load(project) + + TRUE + + } + + renv_bootstrap_profile_load <- function(project) { + + # if RENV_PROFILE is already set, just use that + profile <- Sys.getenv("RENV_PROFILE", unset = NA) + if (!is.na(profile) && nzchar(profile)) + return(profile) + + # check for a profile file (nothing to do if it doesn't exist) + path <- renv_bootstrap_paths_renv("profile", profile = FALSE) + if (!file.exists(path)) + return(NULL) + + # read the profile, and set it if it exists + contents <- readLines(path, warn = FALSE) + if (length(contents) == 0L) + return(NULL) + + # set RENV_PROFILE + profile <- contents[[1L]] + if (!profile %in% c("", "default")) + Sys.setenv(RENV_PROFILE = profile) + + profile + + } + + renv_bootstrap_profile_prefix <- function() { + profile <- renv_bootstrap_profile_get() + if (!is.null(profile)) + return(file.path("profiles", profile, "renv")) + } + + renv_bootstrap_profile_get <- function() { + profile <- Sys.getenv("RENV_PROFILE", unset = "") + renv_bootstrap_profile_normalize(profile) + } + + renv_bootstrap_profile_set <- function(profile) { + profile <- renv_bootstrap_profile_normalize(profile) + if (is.null(profile)) + Sys.unsetenv("RENV_PROFILE") + else + Sys.setenv(RENV_PROFILE = profile) + } + + renv_bootstrap_profile_normalize <- function(profile) { + + if (is.null(profile) || profile %in% c("", "default")) + return(NULL) + + profile + + } + + renv_bootstrap_path_absolute <- function(path) { + + substr(path, 1L, 1L) %in% c("~", "/", "\\") || ( + substr(path, 1L, 1L) %in% c(letters, LETTERS) && + substr(path, 2L, 3L) %in% c(":/", ":\\") + ) + + } + + renv_bootstrap_paths_renv <- function(..., profile = TRUE, project = NULL) { + renv <- Sys.getenv("RENV_PATHS_RENV", unset = "renv") + root <- if (renv_bootstrap_path_absolute(renv)) NULL else project + prefix <- if (profile) renv_bootstrap_profile_prefix() + components <- c(root, renv, prefix, ...) + paste(components, collapse = "/") + } + + renv_bootstrap_project_type <- function(path) { + + descpath <- file.path(path, "DESCRIPTION") + if (!file.exists(descpath)) + return("unknown") + + desc <- tryCatch( + read.dcf(descpath, all = TRUE), + error = identity + ) + + if (inherits(desc, "error")) + return("unknown") + + type <- desc$Type + if (!is.null(type)) + return(tolower(type)) + + package <- desc$Package + if (!is.null(package)) + return("package") + + "unknown" + + } + + renv_bootstrap_user_dir <- function() { + dir <- renv_bootstrap_user_dir_impl() + path.expand(chartr("\\", "/", dir)) + } + + renv_bootstrap_user_dir_impl <- function() { + + # use local override if set + override <- getOption("renv.userdir.override") + if (!is.null(override)) + return(override) + + # use R_user_dir if available + tools <- asNamespace("tools") + if (is.function(tools$R_user_dir)) + return(tools$R_user_dir("renv", "cache")) + + # try using our own backfill for older versions of R + envvars <- c("R_USER_CACHE_DIR", "XDG_CACHE_HOME") + for (envvar in envvars) { + root <- Sys.getenv(envvar, unset = NA) + if (!is.na(root)) + return(file.path(root, "R/renv")) + } + + # use platform-specific default fallbacks + if (Sys.info()[["sysname"]] == "Windows") + file.path(Sys.getenv("LOCALAPPDATA"), "R/cache/R/renv") + else if (Sys.info()[["sysname"]] == "Darwin") + "~/Library/Caches/org.R-project.R/R/renv" + else + "~/.cache/R/renv" + + } + + + renv_json_read <- function(file = NULL, text = NULL) { + + text <- paste(text %||% read(file), collapse = "\n") + + # find strings in the JSON + pattern <- '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]' + locs <- gregexpr(pattern, text, perl = TRUE)[[1]] + + # if any are found, replace them with placeholders + replaced <- text + strings <- character() + replacements <- character() + + if (!identical(c(locs), -1L)) { + + # get the string values + starts <- locs + ends <- locs + attr(locs, "match.length") - 1L + strings <- substring(text, starts, ends) + + # only keep those requiring escaping + strings <- grep("[[\\]{}:]", strings, perl = TRUE, value = TRUE) + + # compute replacements + replacements <- sprintf('"\032%i\032"', seq_along(strings)) + + # replace the strings + mapply(function(string, replacement) { + replaced <<- sub(string, replacement, replaced, fixed = TRUE) + }, strings, replacements) + + } + + # transform the JSON into something the R parser understands + transformed <- replaced + transformed <- gsub("[[{]", "list(", transformed) + transformed <- gsub("[]}]", ")", transformed) + transformed <- gsub(":", "=", transformed, fixed = TRUE) + text <- paste(transformed, collapse = "\n") + + # parse it + json <- parse(text = text, keep.source = FALSE, srcfile = NULL)[[1L]] + + # construct map between source strings, replaced strings + map <- as.character(parse(text = strings)) + names(map) <- as.character(parse(text = replacements)) + + # convert to list + map <- as.list(map) + + # remap strings in object + remapped <- renv_json_remap(json, map) + + # evaluate + eval(remapped, envir = baseenv()) + + } + + renv_json_remap <- function(json, map) { + + # fix names + if (!is.null(names(json))) { + lhs <- match(names(json), names(map), nomatch = 0L) + rhs <- match(names(map), names(json), nomatch = 0L) + names(json)[rhs] <- map[lhs] + } + + # fix values + if (is.character(json)) + return(map[[json]] %||% json) + + # handle true, false, null + if (is.name(json)) { + text <- as.character(json) + if (text == "true") + return(TRUE) + else if (text == "false") + return(FALSE) + else if (text == "null") + return(NULL) + } + + # recurse + if (is.recursive(json)) { + for (i in seq_along(json)) { + json[i] <- list(renv_json_remap(json[[i]], map)) + } + } + + json + + } + + # load the renv profile, if any + renv_bootstrap_profile_load(project) + + # construct path to library root + root <- renv_bootstrap_library_root(project) + + # construct library prefix for platform + prefix <- renv_bootstrap_platform_prefix() + + # construct full libpath + libpath <- file.path(root, prefix) + + # attempt to load + if (renv_bootstrap_load(project, libpath, version)) + return(TRUE) + + # load failed; inform user we're about to bootstrap + prefix <- paste("# Bootstrapping renv", version) + postfix <- paste(rep.int("-", 77L - nchar(prefix)), collapse = "") + header <- paste(prefix, postfix) + message(header) + + # perform bootstrap + bootstrap(version, libpath) + + # exit early if we're just testing bootstrap + if (!is.na(Sys.getenv("RENV_BOOTSTRAP_INSTALL_ONLY", unset = NA))) + return(TRUE) + + # try again to load + if (requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) { + message("* Successfully installed and loaded renv ", version, ".") + return(renv::load()) + } + + # failed to download or load renv; warn the user + msg <- c( + "Failed to find an renv installation: the project will not be loaded.", + "Use `renv::activate()` to re-initialize the project." + ) + + warning(paste(msg, collapse = "\n"), call. = FALSE) + +}) diff --git a/renv/settings.dcf b/renv/settings.dcf new file mode 100644 index 0000000..169d82f --- /dev/null +++ b/renv/settings.dcf @@ -0,0 +1,10 @@ +bioconductor.version: +external.libraries: +ignored.packages: +package.dependency.fields: Imports, Depends, LinkingTo +r.version: +snapshot.type: implicit +use.cache: TRUE +vcs.ignore.cellar: TRUE +vcs.ignore.library: TRUE +vcs.ignore.local: TRUE diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..a2f31d3 --- /dev/null +++ b/styles.css @@ -0,0 +1,112 @@ + +@import url('https://fonts.googleapis.com/css?family=Inter'); +@import url('https://fonts.googleapis.com/css?family=Roboto+Mono'); + +body { + background-color: #10151A; + background-position: center top; + background-size: 300px 117px; + padding-left: 10%; + padding-right: 10%; + color: #C4CDD5; + font-size: 18px; + font-weight: 400; + font-family: Inter; + margin-top: 10px; +} + +hr { + width: 85%; + color: #C4CDD5; +} + +.tocify { + background-color: #10151A; + font-size: 14px; + color: #C4CDD5; + border: 0; +} + +.list-group-item.active, .list-group-item.active:focus, .list-group-item.active:hover { + background-color: #FF5517; + border-color: #FF5517; +} + +.list-group-item { + background-color: #10151A; +} + +h1 { + font-size: 1.4em; + padding-top: 10px; + color: #FF5517; +} + +h2 { + font-size: 1.1em; + padding-top: 10px; + color: #03FFFF; +} + +h3 { + font-size: 1.1em; + padding-top: 10px; + color: white; +} + +.plotly { + margin: 30px; +} + +.rt-page-button-current { + color: #FFF; +} +.rt-thead { + background-color: #10151A; + color: #FFFFFF; + text-align: center; + vertical-align: middle; +} + +.rt-th-content { + text-align: center; + vertical-align: middle; +} + +.ReactTable { + background-color: #171e25; + color: #C4CDD5; + border: none; + font-family: Roboto Mono; + font-size: 0.8em; +} + +.rt-th { + border: 0px solid #000000 !important; + padding-top: 15px; + padding-bottom: 15px; + font-weight: 400; + font-family: Inter; +} +.rt-tr { + padding-top: 5px; + padding-bottom: 5px; +} +.rt-pagination { + margin: 0; + background: #171e25; + opacity: 0.5; + border-bottom: 1px solid #C4CDD5; + border-top: 1px solid #C4CDD5; +} + +.btn { + color: #FFF; + background: none; + border: none; + padding: 0; +} + +#TOC { +margin: 71px 0px 20px 0px; +} \ No newline at end of file