merge / resolve conflicts w/ main

This commit is contained in:
Jim Myers 2022-10-31 14:36:57 -04:00
commit bf728ca685
16 changed files with 2656 additions and 29311 deletions

4
.prettierrc Normal file
View File

@ -0,0 +1,4 @@
{
"printWidth": 120,
"semi": true
}

View File

@ -19,6 +19,6 @@ More Details at [ShroomDK](https://sdk.flipsidecrypto.xyz)
| Language | Version | Status |
| ------------------------ | ------- | ---------------------------------------------------------------------------------- |
| ✅ [JS/TypeScript](./js) | 1.0.0 | ![tests](https://github.com/flipsidecrypto/sdk/actions/workflows/ci_js.yml/badge.svg) |
| ✅ [JS/TypeScript](./js) | 1.1.1 | ![tests](https://github.com/flipsidecrypto/sdk/actions/workflows/ci_js.yml/badge.svg) |
| ✅ [Python](./python/) | 1.0.2 | [![tests](https://github.com/FlipsideCrypto/sdk/actions/workflows/ci_python.yml/badge.svg)](https://github.com/FlipsideCrypto/sdk/actions/workflows/ci_python.yml) |
| ✅ [R](./r/shroomDK/) | 0.1.1 | available on CRAN |

View File

@ -0,0 +1,7 @@
/**
* @type {import('@types/eslint').Linter.Config}
*/
module.exports = {
root: true,
ignorePatterns: ["node_modules", "dist", "public"],
};

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,7 @@
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
"@types/eslint": "^8.4.8",
"@types/jest": "^27.5.2",
"@types/node": "^16.11.45",
"@types/react": "^18.0.15",

View File

@ -12,7 +12,7 @@ interface ButtonProps {
function getBg(color: string) {
let bgColor = "bg-[#7C7C7C]";
let bgColorHover = "hover:bg-[#BCBCca]";
if (color == "blue") {
if (color === "blue") {
bgColor = "bg-[#2A3492]";
bgColorHover = "hover:bg-[#2A34ca]";
} else if (color === "green") {

View File

@ -1,6 +1,5 @@
import { useEffect, useState } from "react";
import toast from "react-hot-toast";
import { QueryResultSet } from "@flipsidecrypto/sdk";
import { Input } from "../components/input";
import { RetroButton } from "../components/retro-buttons";

View File

@ -1885,6 +1885,14 @@
"@types/estree" "*"
"@types/json-schema" "*"
"@types/eslint@^8.4.8":
version "8.4.8"
resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.8.tgz#720dd6a32b8219b9aba1a07b13e9d03b622695fd"
integrity sha512-zUCKQI1bUCTi+0kQs5ZQzQ/XILWRLIlh15FXWNykJ+NG3TMKMVvwwC6GP3DR1Ylga15fB7iAExSzc4PNlR5i3w==
dependencies:
"@types/estree" "*"
"@types/json-schema" "*"
"@types/estree@*":
version "1.0.0"
resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz"

View File

@ -0,0 +1,147 @@
---
title: "shroomDK-Example"
author: "Charliemarketplace"
date: '2022-10-06'
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
# Intro to ShroomDK
The shroomDK package has full access to all the data within Flipside Crypto. You just need your own API-key,
which is free at: https://sdk.flipsidecrypto.xyz/shroomdk
For this documentation, you can use this API key to test things out in R. **But it is capped at 10,000 queries a day among all public users**: `2a4caf06-d503-4c96-a30e-a13dc34792d0`
It is highly recommended you get your own key for free at https://sdk.flipsidecrypto.xyz/shroomdk - but just to get you off the ground you can use the shared key at first.
Here is some example code to get you started!
Let's look at Bored Ape Yacht Club NFT transfers over time. First, we'll set a Block_Number
maximum to make our analysis reproducible. Let's use Block_Number = 15680000
This query was made within the flipsidecrypto.xyz SQL tool and we can copy this query to use within R
by storing the query in a character (i.e., double quotes: "").
Notice that the NFT Address is made lowercase to conform to how Flipside's Snowflake database stores them.
The EZ_NFT_Transfers table has sales, mints, and other forms of transfer of 1,000s of NFTs!
```{r, warning = FALSE, message = FALSE}
library(plotly)
library(dplyr)
bayc_transfers_query <- "
SELECT BLOCK_NUMBER, BLOCK_TIMESTAMP, NFT_ADDRESS, PROJECT_NAME, NFT_TO_ADDRESS, TOKENID
FROM ethereum.core.ez_nft_transfers
WHERE BLOCK_NUMBER <= 15680000 AND
NFT_ADDRESS = LOWER('0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D')
ORDER BY BLOCK_NUMBER DESC
"
```
If you haven't installed shroomDK, scroll up to the beginning of the docs to find install instructions.
shroomDK is in processing to be added to CRAN! So, soon, install.packages('shroomDK') will work within R.
```{r, warning = FALSE, message = FALSE}
# Get your API key for free at sdk.flipsidecrypto.xyz/shroomdk
bayc_transfers <- shroomDK::auto_paginate_query(query = bayc_transfers_query,
api_key = "2a4caf06-d503-4c96-a30e-a13dc34792d0") # get your own API Key to avoid rate limits!
```
This query returns over 86,000 historical transfers!
With R you can group by block_timestamp at the day level and plot transfers over time! Here we'll use the
dplyr and plotly packages.
```{r}
daily_transfers <- bayc_transfers %>%
dplyr::mutate(day = as.Date(BLOCK_TIMESTAMP)) %>%
dplyr::group_by(day) %>%
dplyr::summarise(num_transfers = n())
```
The plot shows that May 1, 2021 was the most popular transfer day (likely the day the public mint went viral);
but there are other pockets are many transfers including May 1, 2022, a highly volatile time for all of crypto.
```{r}
plotly::plot_ly(data = daily_transfers, x = ~day, y = ~num_transfers, mode = 'lines', type = 'scatter')
```
What if we were curious who the current holders of each token id are?
With R it's simple!
Group by token_id, order by block_number DESCENDING (recent blocks up top), and
pick the most recent transfer recipient (the person who most recently received token id is by
definition the owner of that token id as of our block number).
```{r, warning = FALSE, message = FALSE}
bayc_holders <- bayc_transfers %>%
dplyr::mutate(TOKENID = as.numeric(TOKENID)) %>%
dplyr::group_by(TOKENID) %>%
dplyr::arrange( desc(BLOCK_NUMBER) ) %>%
dplyr::summarise(current_holder = first(NFT_TO_ADDRESS))
```
Are there BAYCs being held in "cold storage"? Wallets that hold tokens/NFTs but have never initiated
a transaction?
With this bayc_holders list, we can *ask shroomDK* for activity from these addresses!
First, let's template the query and use R to swap in parameters (including large ones like 10,000
addresses in the WHERE clause).
We'll swap: ADRRESSLIST, _MIN_BLOCK_, and _MAX_BLOCK_ using R's gsub function.
```{r, warning = FALSE, message = FALSE}
activity_query <- {
"
with select_tx AS (
SELECT BLOCK_TIMESTAMP, TX_HASH, FROM_ADDRESS as ADDRESS FROM ethereum.core.fact_transactions
WHERE FROM_ADDRESS IN ('ADDRESSLIST') AND
BLOCK_NUMBER >= _MIN_BLOCK_ AND
BLOCK_NUMBER <= _MAX_BLOCK_
ORDER BY BLOCK_NUMBER DESC
)
SELECT ADDRESS, COUNT(*) as num_tx,
count(DISTINCT(date_trunc('DAY', block_timestamp))) as num_days,
MAX(block_timestamp) as last_tx_date FROM
select_tx
GROUP BY ADDRESS
"
}
# paste together the unique addresses from our 10,000 BAYC NFTs to work with SQL.
alist <- paste0(tolower(unique(bayc_holders$current_holder)), collapse = "','")
# swap parameters
activity_query <- gsub('ADDRESSLIST', replacement = alist, x = activity_query)
activity_query <- gsub('_MIN_BLOCK_', replacement = 0, x = activity_query)
activity_query <- gsub('_MAX_BLOCK_', replacement = 15680000, x = activity_query)
```
Our activity_query is now HUGE. It has 1,000s of addresses in its where clause. But shroomDK doesn't care!
```{r, warning = FALSE, message = FALSE}
bayc_holder_activity <- shroomDK::auto_paginate_query(activity_query, api_key = "2a4caf06-d503-4c96-a30e-a13dc34792d0")
```
As of block 15680000, there are 6,079 unique BAYC holders with at least 1 transaction.
Let's FULL join these tables in R and see if there are any bayc_holders with NA transactions (i.e., they are cold
storage addresses that have never initiated a transaction!).
```{r}
bayc_holders <- merge(bayc_holders, bayc_holder_activity,
all.x = TRUE, all.y = TRUE, by.x = 'current_holder', by.y = 'ADDRESS')
bayc_holders$status <- ifelse(is.na(bayc_holders$NUM_TX), "Cold", "Active")
```
Note, some addresses hold multiple tokens, so each row here is only unique at the token level.
While "Cold Storage" is the terminology used, technically BAYC can be held within contracts (e.g., fractionalized NFTs Vaults or gnosis safes) or be burnt (held by 0x0000....0000dead).
```{r}
plotly::plot_ly(bayc_holders, x = ~status, type = 'histogram')
```
1,024 of the 10,000 BAYC NFTs are held in either contracts or cold storage addresses!
With shroomDK we can query flipside crypto's blockchain data with even advanced queries that ask for information on 1,000s of addresses in a single WHERE clause - and bring it directly into R for advanced plotting.

File diff suppressed because one or more lines are too long

7
js/.eslintrc.js Normal file
View File

@ -0,0 +1,7 @@
/**
* @type {import('@types/eslint').Linter.Config}
*/
module.exports = {
root: true,
ignorePatterns: ["node_modules", "dist", "public"],
};

View File

@ -1,6 +1,6 @@
{
"name": "@flipsidecrypto/sdk",
"version": "1.1.0",
"version": "1.1.1",
"description": "The official Flipside Crypto SDK",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@ -30,6 +30,7 @@
"author": "dev@flipsidecrypto.com",
"license": "MIT",
"dependencies": {
"@types/eslint": "^8.4.8",
"axios": "^0.27.2"
}
}

View File

@ -15,9 +15,13 @@ const PARSE_ERROR_MSG =
export class API implements ApiClient {
#baseUrl: string;
#headers: Record<string, string>;
#sdkVersion: string;
#sdkPackage: string;
constructor(baseUrl: string, apiKey: string) {
constructor(baseUrl: string, sdkPackage: string, sdkVersion: string, apiKey: string) {
this.#baseUrl = baseUrl;
this.#sdkPackage = sdkPackage;
this.#sdkVersion = sdkVersion;
this.#headers = {
Accept: "application/json",
"Content-Type": "application/json",
@ -38,6 +42,8 @@ export class API implements ApiClient {
sql: query.sql,
ttl_minutes: query.ttlMinutes,
cached: query.cached,
sdk_package: this.#sdkPackage,
sdk_version: this.#sdkVersion,
},
{ headers: this.#headers }
);

View File

@ -1,14 +1,18 @@
import { API } from "./api";
import { QueryIntegration } from "./integrations";
import { version } from '../package.json';
const API_BASE_URL = "https://api.flipsidecrypto.com";
const SDK_PACKAGE = "js";
const SDK_VERSION = version;
export class Flipside {
query: QueryIntegration;
constructor(apiKey: string, apiBaseUrl: string = API_BASE_URL) {
// Setup API, which will be passed to integrations
const api = new API(apiBaseUrl, apiKey);
const api = new API(apiBaseUrl, SDK_PACKAGE, SDK_VERSION, apiKey);
// declare integrations on Flipside client
this.query = new QueryIntegration(api);

View File

@ -33,7 +33,7 @@
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "resolveJsonModule": true, /* Enable importing .json files */
"resolveJsonModule": true, /* Enable importing .json files */
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */

View File

@ -47,11 +47,29 @@
resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.1.tgz#e2c6e73e0bdeb2521d00756d099218e9f5d90a04"
integrity sha512-/zPMqDkzSZ8t3VtxOa4KPq7uzzW978M9Tvh+j7GHKuo6k6GTLxPJ4J5gE5cjfJ26pnXst0N5Hax8Sr0T2Mi9zQ==
"@types/eslint@^8.4.8":
version "8.4.8"
resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.8.tgz#720dd6a32b8219b9aba1a07b13e9d03b622695fd"
integrity sha512-zUCKQI1bUCTi+0kQs5ZQzQ/XILWRLIlh15FXWNykJ+NG3TMKMVvwwC6GP3DR1Ylga15fB7iAExSzc4PNlR5i3w==
dependencies:
"@types/estree" "*"
"@types/json-schema" "*"
"@types/estree@*":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2"
integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==
"@types/istanbul-lib-coverage@^2.0.1":
version "2.0.4"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44"
integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==
"@types/json-schema@*":
version "7.0.11"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==
"@vitest/ui@latest":
version "0.12.6"
resolved "https://registry.yarnpkg.com/@vitest/ui/-/ui-0.12.6.tgz#6dba9bd6781ce1280452e4b25160b3914eb5e435"