From f4d2abe4cf8443595a88007a38974b034eb97f6d Mon Sep 17 00:00:00 2001
From: "Carlos R. Mercado" <107061601+charlieflipside@users.noreply.github.com>
Date: Mon, 31 Oct 2022 14:05:59 -0400
Subject: [PATCH] removed warnings
---
examples/r/shroomDK_BAYC_example.Rmd | 8 +-
examples/r/shroomDK_BAYC_example.html | 388 ++++++++++++--------------
2 files changed, 178 insertions(+), 218 deletions(-)
diff --git a/examples/r/shroomDK_BAYC_example.Rmd b/examples/r/shroomDK_BAYC_example.Rmd
index 32e309b..b2c4baa 100644
--- a/examples/r/shroomDK_BAYC_example.Rmd
+++ b/examples/r/shroomDK_BAYC_example.Rmd
@@ -44,7 +44,7 @@ FROM ethereum.core.ez_nft_transfers
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}
+```{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!
@@ -75,7 +75,7 @@ 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}
+```{r, warning = FALSE, message = FALSE}
bayc_holders <- bayc_transfers %>%
dplyr::mutate(TOKENID = as.numeric(TOKENID)) %>%
dplyr::group_by(TOKENID) %>%
@@ -92,7 +92,7 @@ First, let's template the query and use R to swap in parameters (including large
addresses in the WHERE clause).
We'll swap: ADRRESSLIST, _MIN_BLOCK_, and _MAX_BLOCK_ using R's gsub function.
-```{r}
+```{r, warning = FALSE, message = FALSE}
activity_query <- {
"
with select_tx AS (
@@ -122,7 +122,7 @@ GROUP BY ADDRESS
Our activity_query is now HUGE. It has 1,000s of addresses in its where clause. But shroomDK doesn't care!
-```{r}
+```{r, warning = FALSE, message = FALSE}
bayc_holder_activity <- shroomDK::auto_paginate_query(activity_query, api_key = "2a4caf06-d503-4c96-a30e-a13dc34792d0")
```
diff --git a/examples/r/shroomDK_BAYC_example.html b/examples/r/shroomDK_BAYC_example.html
index 7068b3d..4ff63d1 100644
--- a/examples/r/shroomDK_BAYC_example.html
+++ b/examples/r/shroomDK_BAYC_example.html
@@ -1147,45 +1147,45 @@ HTMLWidgets.widget({
var height = instance.height || height;
Plotly.relayout(el.id, {width: width, height: height});
}
- },
-
+ },
+
renderValue: function(el, x, instance) {
-
- // Plotly.relayout() mutates the plot input object, so make sure to
+
+ // Plotly.relayout() mutates the plot input object, so make sure to
// keep a reference to the user-supplied width/height *before*
// we call Plotly.plot();
var lay = x.layout || {};
instance.width = lay.width;
instance.height = lay.height;
instance.autosize = lay.autosize || true;
-
- /*
+
+ /*
/ 'inform the world' about highlighting options this is so other
- / crosstalk libraries have a chance to respond to special settings
- / such as persistent selection.
+ / crosstalk libraries have a chance to respond to special settings
+ / such as persistent selection.
/ AFAIK, leaflet is the only library with such intergration
/ https://github.com/rstudio/leaflet/pull/346/files#diff-ad0c2d51ce5fdf8c90c7395b102f4265R154
*/
var ctConfig = crosstalk.var('plotlyCrosstalkOpts').set(x.highlight);
-
+
if (typeof(window) !== "undefined") {
// make sure plots don't get created outside the network (for on-prem)
window.PLOTLYENV = window.PLOTLYENV || {};
window.PLOTLYENV.BASE_URL = x.base_url;
-
+
// Enable persistent selection when shift key is down
// https://stackoverflow.com/questions/1828613/check-if-a-key-is-down
var persistOnShift = function(e) {
if (!e) window.event;
- if (e.shiftKey) {
- x.highlight.persistent = true;
+ if (e.shiftKey) {
+ x.highlight.persistent = true;
x.highlight.persistentShift = true;
} else {
- x.highlight.persistent = false;
+ x.highlight.persistent = false;
x.highlight.persistentShift = false;
}
};
-
+
// Only relevant if we haven't forced persistent mode at command line
if (!x.highlight.persistent) {
window.onmousemove = persistOnShift;
@@ -1193,10 +1193,10 @@ HTMLWidgets.widget({
}
var graphDiv = document.getElementById(el.id);
-
+
// TODO: move the control panel injection strategy inside here...
HTMLWidgets.addPostRenderHandler(function() {
-
+
// lower the z-index of the modebar to prevent it from highjacking hover
// (TODO: do this via CSS?)
// https://github.com/ropensci/plotly/issues/956
@@ -1206,60 +1206,60 @@ HTMLWidgets.widget({
modebars[i].style.zIndex = 1;
}
});
-
+
// inject a "control panel" holding selectize/dynamic color widget(s)
if ((x.selectize || x.highlight.dynamic) && !instance.plotly) {
var flex = document.createElement("div");
flex.class = "plotly-crosstalk-control-panel";
flex.style = "display: flex; flex-wrap: wrap";
-
+
// inject the colourpicker HTML container into the flexbox
if (x.highlight.dynamic) {
var pickerDiv = document.createElement("div");
-
+
var pickerInput = document.createElement("input");
pickerInput.id = el.id + "-colourpicker";
pickerInput.placeholder = "asdasd";
-
+
var pickerLabel = document.createElement("label");
pickerLabel.for = pickerInput.id;
pickerLabel.innerHTML = "Brush color ";
-
+
pickerDiv.appendChild(pickerLabel);
pickerDiv.appendChild(pickerInput);
flex.appendChild(pickerDiv);
}
-
+
// inject selectize HTML containers (one for every crosstalk group)
if (x.selectize) {
var ids = Object.keys(x.selectize);
-
+
for (var i = 0; i < ids.length; i++) {
var container = document.createElement("div");
container.id = ids[i];
container.style = "width: 80%; height: 10%";
container.class = "form-group crosstalk-input-plotly-highlight";
-
+
var label = document.createElement("label");
label.for = ids[i];
label.innerHTML = x.selectize[ids[i]].group;
label.class = "control-label";
-
+
var selectDiv = document.createElement("div");
var select = document.createElement("select");
select.multiple = true;
-
+
selectDiv.appendChild(select);
container.appendChild(label);
container.appendChild(selectDiv);
flex.appendChild(container);
}
}
-
+
// finally, insert the flexbox inside the htmlwidget container,
// but before the plotly graph div
graphDiv.parentElement.insertBefore(flex, graphDiv);
-
+
if (x.highlight.dynamic) {
var picker = $("#" + pickerInput.id);
var colors = x.highlight.color || [];
@@ -1289,20 +1289,20 @@ HTMLWidgets.widget({
});
}
}
-
+
// if no plot exists yet, create one with a particular configuration
if (!instance.plotly) {
-
+
var plot = Plotly.newPlot(graphDiv, x);
instance.plotly = true;
-
+
} else if (x.layout.transition) {
-
+
var plot = Plotly.react(graphDiv, x);
-
+
} else {
-
- // this is essentially equivalent to Plotly.newPlot(), but avoids creating
+
+ // this is essentially equivalent to Plotly.newPlot(), but avoids creating
// a new webgl context
// https://github.com/plotly/plotly.js/blob/2b24f9def901831e61282076cf3f835598d56f0e/src/plot_api/plot_api.js#L531-L532
@@ -1313,7 +1313,7 @@ HTMLWidgets.widget({
graphDiv.layout = undefined;
var plot = Plotly.newPlot(graphDiv, x);
}
-
+
// Trigger plotly.js calls defined via `plotlyProxy()`
plot.then(function() {
if (HTMLWidgets.shinyMode) {
@@ -1322,8 +1322,8 @@ HTMLWidgets.widget({
if (!gd) {
throw new Error("Couldn't find plotly graph with id: " + msg.id);
}
- // This isn't an official plotly.js method, but it's the only current way to
- // change just the configuration of a plot
+ // This isn't an official plotly.js method, but it's the only current way to
+ // change just the configuration of a plot
// https://community.plot.ly/t/update-config-function/9057
if (msg.method == "reconfig") {
Plotly.react(gd, gd.data, gd.layout, msg.args);
@@ -1336,7 +1336,7 @@ HTMLWidgets.widget({
Plotly[msg.method].apply(null, args);
});
}
-
+
// plotly's mapbox API doesn't currently support setting bounding boxes
// https://www.mapbox.com/mapbox-gl-js/example/fitbounds/
// so we do this manually...
@@ -1352,9 +1352,9 @@ HTMLWidgets.widget({
var mapObj = graphDiv._fullLayout[id]._subplot.map;
mapObj.fitBounds(args.bounds, args.options);
}
-
+
});
-
+
// Attach attributes (e.g., "key", "z") to plotly event data
function eventDataWithKey(eventData) {
if (eventData === undefined || !eventData.hasOwnProperty("points")) {
@@ -1362,34 +1362,34 @@ HTMLWidgets.widget({
}
return eventData.points.map(function(pt) {
var obj = {
- curveNumber: pt.curveNumber,
- pointNumber: pt.pointNumber,
+ curveNumber: pt.curveNumber,
+ pointNumber: pt.pointNumber,
x: pt.x,
y: pt.y
};
-
+
// If 'z' is reported with the event data, then use it!
if (pt.hasOwnProperty("z")) {
obj.z = pt.z;
}
-
+
if (pt.hasOwnProperty("customdata")) {
obj.customdata = pt.customdata;
}
-
- /*
+
+ /*
TL;DR: (I think) we have to select the graph div (again) to attach keys...
-
- Why? Remember that crosstalk will dynamically add/delete traces
+
+ Why? Remember that crosstalk will dynamically add/delete traces
(see traceManager.prototype.updateSelection() below)
For this reason, we can't simply grab keys from x.data (like we did previously)
- Moreover, we can't use _fullData, since that doesn't include
- unofficial attributes. It's true that click/hover events fire with
+ Moreover, we can't use _fullData, since that doesn't include
+ unofficial attributes. It's true that click/hover events fire with
pt.data, but drag events don't...
*/
var gd = document.getElementById(el.id);
var trace = gd.data[pt.curveNumber];
-
+
if (!trace._isSimpleKey) {
var attrsToAttach = ["key"];
} else {
@@ -1397,7 +1397,7 @@ HTMLWidgets.widget({
obj.key = trace.key;
var attrsToAttach = [];
}
-
+
for (var i = 0; i < attrsToAttach.length; i++) {
var attr = trace[attrsToAttach[i]];
if (Array.isArray(attr)) {
@@ -1413,13 +1413,13 @@ HTMLWidgets.widget({
return obj;
});
}
-
-
+
+
var legendEventData = function(d) {
// if legendgroup is not relevant just return the trace
var trace = d.data[d.curveNumber];
if (!trace.legendgroup) return trace;
-
+
// if legendgroup was specified, return all traces that match the group
var legendgrps = d.data.map(function(trace){ return trace.legendgroup; });
var traces = [];
@@ -1428,14 +1428,14 @@ HTMLWidgets.widget({
traces.push(d.data[i]);
}
}
-
+
return traces;
};
-
+
// send user input event data to shiny
if (HTMLWidgets.shinyMode && Shiny.setInputValue) {
-
+
// Some events clear other input values
// TODO: always register these?
var eventClearMap = {
@@ -1443,7 +1443,7 @@ HTMLWidgets.widget({
plotly_unhover: ["plotly_hover"],
plotly_doubleclick: ["plotly_click"]
};
-
+
Object.keys(eventClearMap).map(function(evt) {
graphDiv.on(evt, function() {
var inputsToClear = eventClearMap[evt];
@@ -1452,7 +1452,7 @@ HTMLWidgets.widget({
});
});
});
-
+
var eventDataFunctionMap = {
plotly_click: eventDataWithKey,
plotly_sunburstclick: eventDataWithKey,
@@ -1460,7 +1460,7 @@ HTMLWidgets.widget({
plotly_unhover: eventDataWithKey,
// If 'plotly_selected' has already been fired, and you click
// on the plot afterwards, this event fires `undefined`?!?
- // That might be considered a plotly.js bug, but it doesn't make
+ // That might be considered a plotly.js bug, but it doesn't make
// sense for this input change to occur if `d` is falsy because,
// even in the empty selection case, `d` is truthy (an object),
// and the 'plotly_deselect' event will reset this input
@@ -1476,7 +1476,7 @@ HTMLWidgets.widget({
plotly_legenddoubleclick: legendEventData,
plotly_clickannotation: function(d) { return d.fullAnnotation }
};
-
+
var registerShinyValue = function(event) {
var eventDataPreProcessor = eventDataFunctionMap[event] || function(d) { return d ? d : el.id };
// some events are unique to the R package
@@ -1490,53 +1490,53 @@ HTMLWidgets.widget({
);
});
}
-
+
var shinyEvents = x.shinyEvents || [];
shinyEvents.map(registerShinyValue);
}
-
+
// Given an array of {curveNumber: x, pointNumber: y} objects,
// return a hash of {
- // set1: {value: [key1, key2, ...], _isSimpleKey: false},
+ // set1: {value: [key1, key2, ...], _isSimpleKey: false},
// set2: {value: [key3, key4, ...], _isSimpleKey: false}
// }
function pointsToKeys(points) {
var keysBySet = {};
for (var i = 0; i < points.length; i++) {
-
+
var trace = graphDiv.data[points[i].curveNumber];
if (!trace.key || !trace.set) {
continue;
}
-
+
// set defaults for this keySet
- // note that we don't track the nested property (yet) since we always
+ // note that we don't track the nested property (yet) since we always
// emit the union -- http://cpsievert.github.io/talks/20161212b/#21
keysBySet[trace.set] = keysBySet[trace.set] || {
value: [],
_isSimpleKey: trace._isSimpleKey
};
-
+
// Use pointNumber by default, but aggregated traces should emit pointNumbers
var ptNum = points[i].pointNumber;
var hasPtNum = typeof ptNum === "number";
var ptNum = hasPtNum ? ptNum : points[i].pointNumbers;
-
- // selecting a point of a "simple" trace means: select the
+
+ // selecting a point of a "simple" trace means: select the
// entire key attached to this trace, which is useful for,
- // say clicking on a fitted line to select corresponding observations
+ // say clicking on a fitted line to select corresponding observations
var key = trace._isSimpleKey ? trace.key : Array.isArray(ptNum) ? ptNum.map(function(idx) { return trace.key[idx]; }) : trace.key[ptNum];
// http://stackoverflow.com/questions/10865025/merge-flatten-an-array-of-arrays-in-javascript
var keyFlat = trace._isNestedKey ? [].concat.apply([], key) : key;
-
+
// TODO: better to only add new values?
keysBySet[trace.set].value = keysBySet[trace.set].value.concat(keyFlat);
}
-
+
return keysBySet;
}
-
-
+
+
x.highlight.color = x.highlight.color || [];
// make sure highlight color is an array
if (!Array.isArray(x.highlight.color)) {
@@ -1558,23 +1558,23 @@ HTMLWidgets.widget({
// register event listeners for all sets
for (var i = 0; i < allSets.length; i++) {
-
+
var set = allSets[i];
var selection = new crosstalk.SelectionHandle(set);
var filter = new crosstalk.FilterHandle(set);
-
+
var filterChange = function(e) {
removeBrush(el);
traceManager.updateFilter(set, e.value);
};
filter.on("change", filterChange);
-
-
+
+
var selectionChange = function(e) {
-
+
// Workaround for 'plotly_selected' now firing previously selected
// points (in addition to new ones) when holding shift key. In our case,
- // we just want the new keys
+ // we just want the new keys
if (x.highlight.on === "plotly_selected" && x.highlight.persistentShift) {
// https://stackoverflow.com/questions/1187518/how-to-get-the-difference-between-two-arrays-in-javascript
Array.prototype.diff = function(a) {
@@ -1582,12 +1582,12 @@ HTMLWidgets.widget({
};
e.value = e.value.diff(e.oldValue);
}
-
+
// array of "event objects" tracking the selection history
// this is used to avoid adding redundant selections
var selectionHistory = crosstalk.var("plotlySelectionHistory").get() || [];
-
- // Construct an event object "defining" the current event.
+
+ // Construct an event object "defining" the current event.
var event = {
receiverID: traceManager.gd.id,
plotlySelectionColour: crosstalk.group(set).var("plotlySelectionColour").get()
@@ -1603,7 +1603,7 @@ HTMLWidgets.widget({
}
}
}
-
+
// accumulate history for persistent selection
if (!x.highlight.persistent) {
selectionHistory = [event];
@@ -1611,7 +1611,7 @@ HTMLWidgets.widget({
selectionHistory.push(event);
}
crosstalk.var("plotlySelectionHistory").set(selectionHistory);
-
+
// do the actual updating of traces, frames, and the selectize widget
traceManager.updateSelection(set, e.value);
// https://github.com/selectize/selectize.js/blob/master/docs/api.md#methods_items
@@ -1624,7 +1624,7 @@ HTMLWidgets.widget({
}
}
selection.on("change", selectionChange);
-
+
// Set a crosstalk variable selection value, triggering an update
var turnOn = function(e) {
if (e) {
@@ -1641,7 +1641,7 @@ HTMLWidgets.widget({
turnOn = debounce(turnOn, x.highlight.debounce);
}
graphDiv.on(x.highlight.on, turnOn);
-
+
graphDiv.on(x.highlight.off, function turnOff(e) {
// remove any visual clues
removeBrush(el);
@@ -1650,7 +1650,7 @@ HTMLWidgets.widget({
// trigger the actual removal of selection traces
selection.set(null, {sender: el});
});
-
+
// register a callback for selectize so that there is bi-directional
// communication between the widget and direct manipulation events
if (x.selectize) {
@@ -1666,7 +1666,7 @@ HTMLWidgets.widget({
};
var select = $("#" + selectizeID).find("select")[0];
var selectize = $(select).selectize(opts)[0].selectize;
- // NOTE: this callback is triggered when *directly* altering
+ // NOTE: this callback is triggered when *directly* altering
// dropdown items
selectize.on("change", function() {
var currentItems = traceManager.groupSelections[set] || [];
@@ -1676,21 +1676,21 @@ HTMLWidgets.widget({
selectize.removeItem(currentItems[i], true);
}
}
- var newItems = selectize.items.filter(function(idx) {
+ var newItems = selectize.items.filter(function(idx) {
return currentItems.indexOf(idx) < 0;
});
if (newItems.length > 0) {
traceManager.updateSelection(set, newItems);
} else {
// Item has been removed...
- // TODO: this logic won't work for dynamically changing palette
+ // TODO: this logic won't work for dynamically changing palette
traceManager.updateSelection(set, null);
traceManager.updateSelection(set, selectize.items);
}
});
}
} // end of selectionChange
-
+
} // end of renderValue
}); // end of widget definition
@@ -1703,10 +1703,10 @@ function TraceManager(graphDiv, highlight) {
this.gd = graphDiv;
// Preserve the original data.
- // TODO: try using Lib.extendFlat() as done in
- // https://github.com/plotly/plotly.js/pull/1136
+ // TODO: try using Lib.extendFlat() as done in
+ // https://github.com/plotly/plotly.js/pull/1136
this.origData = JSON.parse(JSON.stringify(graphDiv.data));
-
+
// avoid doing this over and over
this.origOpacity = [];
for (var i = 0; i < this.origData.length; i++) {
@@ -1716,7 +1716,7 @@ function TraceManager(graphDiv, highlight) {
// key: group name, value: null or array of keys representing the
// most recently received selection for that group.
this.groupSelections = {};
-
+
// selection parameters (e.g., transient versus persistent selection)
this.highlight = highlight;
}
@@ -1728,11 +1728,11 @@ TraceManager.prototype.close = function() {
TraceManager.prototype.updateFilter = function(group, keys) {
if (typeof(keys) === "undefined" || keys === null) {
-
+
this.gd.data = JSON.parse(JSON.stringify(this.origData));
-
+
} else {
-
+
var traces = [];
for (var i = 0; i < this.origData.length; i++) {
var trace = this.origData[i];
@@ -1741,7 +1741,7 @@ TraceManager.prototype.updateFilter = function(group, keys) {
}
var matchFunc = getMatchFunc(trace);
var matches = matchFunc(trace.key, keys);
-
+
if (matches.length > 0) {
if (!trace._isSimpleKey) {
// subsetArrayAttrs doesn't mutate trace (it makes a modified clone)
@@ -1751,22 +1751,22 @@ TraceManager.prototype.updateFilter = function(group, keys) {
}
}
}
-
+
this.gd.data = traces;
Plotly.redraw(this.gd);
-
+
// NOTE: we purposely do _not_ restore selection(s), since on filter,
- // axis likely will update, changing the pixel -> data mapping, leading
+ // axis likely will update, changing the pixel -> data mapping, leading
// to a likely mismatch in the brush outline and highlighted marks
-
+
};
TraceManager.prototype.updateSelection = function(group, keys) {
-
+
if (keys !== null && !Array.isArray(keys)) {
throw new Error("Invalid keys argument; null or array expected");
}
-
+
// if selection has been cleared, or if this is transient
// selection, delete the "selection traces"
var nNewTraces = this.gd.data.length - this.origData.length;
@@ -1788,22 +1788,22 @@ TraceManager.prototype.updateSelection = function(group, keys) {
}
}
}
-
+
if (keys === null) {
-
+
Plotly.restyle(this.gd, {"opacity": this.origOpacity});
-
+
} else if (keys.length >= 1) {
-
+
// placeholder for new "selection traces"
var traces = [];
// this variable is set in R/highlight.R
- var selectionColour = crosstalk.group(group).var("plotlySelectionColour").get() ||
+ var selectionColour = crosstalk.group(group).var("plotlySelectionColour").get() ||
this.highlight.color[0];
for (var i = 0; i < this.origData.length; i++) {
- // TODO: try using Lib.extendFlat() as done in
- // https://github.com/plotly/plotly.js/pull/1136
+ // TODO: try using Lib.extendFlat() as done in
+ // https://github.com/plotly/plotly.js/pull/1136
var trace = JSON.parse(JSON.stringify(this.gd.data[i]));
if (!trace.key || trace.set !== group) {
continue;
@@ -1811,25 +1811,25 @@ TraceManager.prototype.updateSelection = function(group, keys) {
// Get sorted array of matching indices in trace.key
var matchFunc = getMatchFunc(trace);
var matches = matchFunc(trace.key, keys);
-
+
if (matches.length > 0) {
// If this is a "simple" key, that means select the entire trace
if (!trace._isSimpleKey) {
trace = subsetArrayAttrs(trace, matches);
}
- // reach into the full trace object so we can properly reflect the
+ // reach into the full trace object so we can properly reflect the
// selection attributes in every view
var d = this.gd._fullData[i];
-
- /*
- / Recursively inherit selection attributes from various sources,
+
+ /*
+ / Recursively inherit selection attributes from various sources,
/ in order of preference:
/ (1) official plotly.js selected attribute
/ (2) highlight(selected = attrs_selected(...))
*/
// TODO: it would be neat to have a dropdown to dynamically specify these!
$.extend(true, trace, this.highlight.selected);
-
+
// if it is defined, override color with the "dynamic brush color""
if (d.marker) {
trace.marker = trace.marker || {};
@@ -1850,7 +1850,7 @@ TraceManager.prototype.updateSelection = function(group, keys) {
// attach a sensible name/legendgroup
trace.name = trace.name || keys.join("
");
trace.legendgroup = trace.legendgroup || keys.join("
");
-
+
// keep track of mapping between this new trace and the trace it targets
// (necessary for updating frames to reflect the selection traces)
trace._originalIndex = i;
@@ -1859,18 +1859,18 @@ TraceManager.prototype.updateSelection = function(group, keys) {
traces.push(trace);
}
}
-
+
if (traces.length > 0) {
-
+
Plotly.addTraces(this.gd, traces).then(function(gd) {
// incrementally add selection traces to frames
- // (this is heavily inspired by Plotly.Plots.modifyFrames()
+ // (this is heavily inspired by Plotly.Plots.modifyFrames()
// in src/plots/plots.js)
var _hash = gd._transitionData._frameHash;
var _frames = gd._transitionData._frames || [];
-
+
for (var i = 0; i < _frames.length; i++) {
-
+
// add to _frames[i].traces *if* this frame references selected trace(s)
var newIndices = [];
for (var j = 0; j < traces.length; j++) {
@@ -1880,24 +1880,24 @@ TraceManager.prototype.updateSelection = function(group, keys) {
_frames[i].traces.push(tr._newIndex);
}
}
-
+
// nothing to do...
if (newIndices.length === 0) {
continue;
}
-
+
var ctr = 0;
var nFrameTraces = _frames[i].data.length;
-
+
for (var j = 0; j < nFrameTraces; j++) {
var frameTrace = _frames[i].data[j];
if (!frameTrace.key || frameTrace.set !== group) {
continue;
}
-
+
var matchFunc = getMatchFunc(frameTrace);
var matches = matchFunc(frameTrace.key, keys);
-
+
if (matches.length > 0) {
if (!trace._isSimpleKey) {
frameTrace = subsetArrayAttrs(frameTrace, matches);
@@ -1916,19 +1916,19 @@ TraceManager.prototype.updateSelection = function(group, keys) {
_frames[i].data.push(frameTrace);
}
}
-
+
// update gd._transitionData._frameHash
_hash[_frames[i].name] = _frames[i];
}
-
+
});
-
+
// dim traces that have a set matching the set of selection sets
var tracesToDim = [],
opacities = [],
sets = Object.keys(this.groupSelections),
n = this.origData.length;
-
+
for (var i = 0; i < n; i++) {
var opacity = this.origOpacity[i] || 1;
// have we already dimmed this trace? Or is this even worth doing?
@@ -1942,28 +1942,28 @@ TraceManager.prototype.updateSelection = function(group, keys) {
opacities.push(opacity * this.highlight.opacityDim);
}
}
-
+
if (tracesToDim.length > 0) {
Plotly.restyle(this.gd, {"opacity": opacities}, tracesToDim);
// turn off the selected/unselected API
Plotly.restyle(this.gd, {"selectedpoints": null});
}
-
+
}
-
+
}
};
-/*
+/*
Note: in all of these match functions, we assume needleSet (i.e. the selected keys)
is a 1D (or flat) array. The real difference is the meaning of haystack.
-findMatches() does the usual thing you'd expect for
-linked brushing on a scatterplot matrix. findSimpleMatches() returns a match iff
-haystack is a subset of the needleSet. findNestedMatches() returns
+findMatches() does the usual thing you'd expect for
+linked brushing on a scatterplot matrix. findSimpleMatches() returns a match iff
+haystack is a subset of the needleSet. findNestedMatches() returns
*/
function getMatchFunc(trace) {
- return (trace._isNestedKey) ? findNestedMatches :
+ return (trace._isNestedKey) ? findNestedMatches :
(trace._isSimpleKey) ? findSimpleMatches : findMatches;
}
@@ -1983,7 +1983,7 @@ function findSimpleMatches(haystack, needleSet) {
var match = haystack.every(function(val) {
return val === null || needleSet.indexOf(val) >= 0;
});
- // yes, this doesn't make much sense other than conforming
+ // yes, this doesn't make much sense other than conforming
// to the output type of the other match functions
return (match) ? [0] : []
}
@@ -1993,8 +1993,8 @@ function findNestedMatches(haystack, needleSet) {
var matches = [];
for (var i = 0; i < haystack.length; i++) {
var hay = haystack[i];
- var match = hay.every(function(val) {
- return val === null || needleSet.indexOf(val) >= 0;
+ var match = hay.every(function(val) {
+ return val === null || needleSet.indexOf(val) >= 0;
});
if (match) {
matches.push(i);
@@ -2042,7 +2042,7 @@ function subsetArray(arr, indices) {
return result;
}
-// Convenience function for removing plotly's brush
+// Convenience function for removing plotly's brush
function removeBrush(el) {
var outlines = el.querySelectorAll(".select-outline");
for (var i = 0; i < outlines.length; i++) {
@@ -2216,8 +2216,8 @@ pre code {
border-radius: 4px;
}
-.tabset-dropdown > .nav-tabs > li.active:before {
- content: "";
+.tabset-dropdown > .nav-tabs > li.active:before, .tabset-dropdown > .nav-tabs.nav-tabs-open:before {
+ content: "\e259";
font-family: 'Glyphicons Halflings';
display: inline-block;
padding: 10px;
@@ -2225,16 +2225,9 @@ pre code {
}
.tabset-dropdown > .nav-tabs.nav-tabs-open > li.active:before {
- content: "";
- border: none;
-}
-
-.tabset-dropdown > .nav-tabs.nav-tabs-open:before {
- content: "";
+ content: "\e258";
font-family: 'Glyphicons Halflings';
- display: inline-block;
- padding: 10px;
- border-right: 1px solid #ddd;
+ border: none;
}
.tabset-dropdown > .nav-tabs > li.active {
@@ -2291,16 +2284,11 @@ pre code {
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. -
- +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
@@ -2315,30 +2303,30 @@ 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 + WHERE BLOCK_NUMBER <= 15680000 AND NFT_ADDRESS = LOWER('0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D') - ORDER BY BLOCK_NUMBER DESC + 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.
- # Get your API key for free at sdk.flipsidecrypto.xyz/shroomdk
+ # 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.
-daily_transfers <- bayc_transfers %>%
- dplyr::mutate(day = as.Date(BLOCK_TIMESTAMP)) %>%
- dplyr::group_by(day) %>%
+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.
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!
@@ -2346,10 +2334,10 @@ are?
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).
-bayc_holders <- bayc_transfers %>%
- dplyr::mutate(TOKENID = as.numeric(TOKENID)) %>%
- dplyr::group_by(TOKENID) %>%
- dplyr::arrange( desc(BLOCK_NUMBER) ) %>%
+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?
@@ -2376,10 +2364,10 @@ GROUP BY ADDRESS
"
}
-# paste together the unique addresses from our 10,000 BAYC NFTs to work with SQL.
+# 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)
@@ -2387,39 +2375,11 @@ GROUP BY ADDRESS
Our activity_query is now HUGE. It has 1,000s of addresses in its
where clause. But shroomDK doesn’t care!
bayc_holder_activity <- shroomDK::auto_paginate_query(activity_query, api_key = "2a4caf06-d503-4c96-a30e-a13dc34792d0")
-## Warning in shroomDK::get_query_from_token(qtoken$token, api_key = api_key):
-## Query is still running! Trying again shortly
-## Warning in get_query_from_token(query_token, api_key, page_number, page_size):
-## Query is still running! Trying again shortly
-
-## Warning in get_query_from_token(query_token, api_key, page_number, page_size):
-## Query is still running! Trying again shortly
-
-## Warning in get_query_from_token(query_token, api_key, page_number, page_size):
-## Query is still running! Trying again shortly
-
-## Warning in get_query_from_token(query_token, api_key, page_number, page_size):
-## Query is still running! Trying again shortly
-
-## Warning in get_query_from_token(query_token, api_key, page_number, page_size):
-## Query is still running! Trying again shortly
-
-## Warning in get_query_from_token(query_token, api_key, page_number, page_size):
-## Query is still running! Trying again shortly
-
-## Warning in get_query_from_token(query_token, api_key, page_number, page_size):
-## Query is still running! Trying again shortly
-
-## Warning in get_query_from_token(query_token, api_key, page_number, page_size):
-## Query is still running! Trying again shortly
-
-## Warning in get_query_from_token(query_token, api_key, page_number, page_size):
-## Query is still running! Trying again shortly
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!).
-bayc_holders <- merge(bayc_holders, bayc_holder_activity,
+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")
@@ -2428,8 +2388,8 @@ 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).
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