Skip to content

Commit

Permalink
OpenSea - update to v2 of api (#15112)
Browse files Browse the repository at this point in the history
* update to v2

* pnpm-lock.yaml

* pnpm-lock.yaml

* update

* fix

* add bottleneck and refactor source

* pnpm-lock.yaml

* update to use correct endpoint

* update summary

* update eventType prop

* updates

* pnpm-lock.yaml
  • Loading branch information
michelle0927 authored Jan 10, 2025
1 parent 5785b70 commit 717258a
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 62 deletions.
38 changes: 25 additions & 13 deletions components/opensea/opensea.app.mjs
Original file line number Diff line number Diff line change
@@ -1,26 +1,38 @@
import { axios } from "@pipedream/platform";
import Bottleneck from "bottleneck";
const limiter = new Bottleneck({
minTime: 200, // 5 requests per second
maxConcurrent: 1,
});
const axiosRateLimiter = limiter.wrap(axios);

export default {
type: "app",
app: "opensea",
propDefinitions: {},
methods: {
async retrieveEvents({
$, contract, eventType, occurredAfter, cursor,
_baseUrl() {
return "https://api.opensea.io/api/v2";
},
_makeRequest({
$ = this,
path,
...otherOpts
}) {
const apiKey = this.$auth.api_key;
return axios($ ?? this, {
url: "https://api.opensea.io/api/v1/events",
params: {
only_opensea: false,
asset_contract_address: contract,
event_type: eventType,
occurred_after: occurredAfter,
cursor,
},
return axiosRateLimiter($, {
url: `${this._baseUrl()}${path}`,
headers: {
"X-API-KEY": apiKey,
"X-API-KEY": this.$auth.api_key,
},
...otherOpts,
});
},
retrieveEvents({
collectionSlug, ...opts
}) {
return this._makeRequest({
path: `/events/collection/${collectionSlug}`,
...opts,
});
},
},
Expand Down
9 changes: 4 additions & 5 deletions components/opensea/package.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
{
"name": "@pipedream/opensea",
"version": "0.0.3",
"version": "0.0.4",
"description": "Pipedream Opensea Components",
"main": "opensea.app.mjs",
"keywords": [
"pipedream",
"opensea"
],
"files": [
"dist"
],
"homepage": "https://pipedream.com/apps/opensea",
"author": "Pipedream <[email protected]> (https://pipedream.com/)",
"publishConfig": {
"access": "public"
},
"dependencies": {
"@pipedream/platform": "^1.2.0"
"@pipedream/platform": "^3.0.3",
"bottleneck": "^2.19.5",
"md5": "^2.3.0"
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import opensea from "../../opensea.app.mjs";
import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform";
import md5 from "md5";

export default {
name: "New Collection Events",
version: "0.0.3",
key: "opensea-new-collection-events",
description:
"Emit new filtered events. [See docs](https://docs.opensea.io/reference/retrieving-asset-events)",
dedupe: "greatest",
name: "New Collection Events",
description: "Emit new filtered events for a collection. [See the documentation](https://docs.opensea.io/reference/list_events_by_collection)",
version: "0.0.4",
dedupe: "unique",
type: "source",
props: {
opensea,
Expand All @@ -18,54 +18,81 @@ export default {
intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
},
},
contractAddress: {
collectionSlug: {
type: "string",
label: "Contract Address",
description: "Collection contract address",
label: "Collection Slug",
description: "Unique string to identify a collection on OpenSea. This can be found by visiting the collection on the OpenSea website and noting the last path parameter.",
},
eventType: {
type: "string",
options: [
"sales",
"listings",
"all",
"cancel",
"listing",
"offer",
"order",
"redemption",
"sale",
"transfer",
],
label: "Event Type",
description: "OpenSea event type",
description: "The type of event to filter by",
default: "all",
optional: true,
},
},
methods: {
getLastTimestamp() {
_getLastTimestamp() {
return this.db.get("lastTimestamp");
},
setLastTimestamp(ts) {
_setLastTimestamp(ts) {
this.db.set("lastTimestamp", ts);
},
},
async run() {
const eventType = this.eventType === "sales"
? "successful"
: "created";
const lastTimestamp = this.getLastTimestamp();
let cursor = null;
do {
const resp = await this.opensea.retrieveEvents({
contract: this.contractAddress,
eventType,
occurredAfter: lastTimestamp,
cursor,
});
resp.asset_events.forEach((event) => {
this.$emit(event, {
id: event.id,
summary: `${event.asset.name} ${this.eventType} event`,
ts: +new Date(event.created_date),
generateMeta(event) {
return {
id: md5(JSON.stringify(event)),
summary: `New ${event.event_type} event`,
ts: event.event_timestamp,
};
},
async processEvent(max) {
const lastTimestamp = this._getLastTimestamp();
let next = null;
let events = [];
do {
const resp = await this.opensea.retrieveEvents({
collectionSlug: this.collectionSlug,
params: {
event_type: this.eventType,
after: lastTimestamp,
next,
},
});
});
if (!cursor && resp.asset_events.length > 0) {
const ts = Math.floor(new Date(resp.asset_events[0].created_date).getTime() / 1000);
this.setLastTimestamp(ts);
if (!resp?.asset_events) {
break;
}
events.push(...resp.asset_events);
next = resp.next;
} while (lastTimestamp && next);

if (!events.length) {
return;
}
cursor = resp.next;
} while (lastTimestamp && cursor);
this._setLastTimestamp(events[0].event_timestamp);
if (max) {
events = events.slice(0, max);
}
events.reverse().forEach((event) => {
this.$emit(event, this.generateMeta(event));
});
},
},
hooks: {
async deploy() {
await this.processEvent(25);
},
},
async run() {
await this.processEvent();
},
};
18 changes: 12 additions & 6 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 717258a

Please sign in to comment.