Skip to content

Commit 717258a

Browse files
authored
OpenSea - update to v2 of api (#15112)
* 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
1 parent 5785b70 commit 717258a

File tree

4 files changed

+106
-62
lines changed

4 files changed

+106
-62
lines changed

components/opensea/opensea.app.mjs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,38 @@
11
import { axios } from "@pipedream/platform";
2+
import Bottleneck from "bottleneck";
3+
const limiter = new Bottleneck({
4+
minTime: 200, // 5 requests per second
5+
maxConcurrent: 1,
6+
});
7+
const axiosRateLimiter = limiter.wrap(axios);
28

39
export default {
410
type: "app",
511
app: "opensea",
612
propDefinitions: {},
713
methods: {
8-
async retrieveEvents({
9-
$, contract, eventType, occurredAfter, cursor,
14+
_baseUrl() {
15+
return "https://api.opensea.io/api/v2";
16+
},
17+
_makeRequest({
18+
$ = this,
19+
path,
20+
...otherOpts
1021
}) {
11-
const apiKey = this.$auth.api_key;
12-
return axios($ ?? this, {
13-
url: "https://api.opensea.io/api/v1/events",
14-
params: {
15-
only_opensea: false,
16-
asset_contract_address: contract,
17-
event_type: eventType,
18-
occurred_after: occurredAfter,
19-
cursor,
20-
},
22+
return axiosRateLimiter($, {
23+
url: `${this._baseUrl()}${path}`,
2124
headers: {
22-
"X-API-KEY": apiKey,
25+
"X-API-KEY": this.$auth.api_key,
2326
},
27+
...otherOpts,
28+
});
29+
},
30+
retrieveEvents({
31+
collectionSlug, ...opts
32+
}) {
33+
return this._makeRequest({
34+
path: `/events/collection/${collectionSlug}`,
35+
...opts,
2436
});
2537
},
2638
},

components/opensea/package.json

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
11
{
22
"name": "@pipedream/opensea",
3-
"version": "0.0.3",
3+
"version": "0.0.4",
44
"description": "Pipedream Opensea Components",
55
"main": "opensea.app.mjs",
66
"keywords": [
77
"pipedream",
88
"opensea"
99
],
10-
"files": [
11-
"dist"
12-
],
1310
"homepage": "https://pipedream.com/apps/opensea",
1411
"author": "Pipedream <support@pipedream.com> (https://pipedream.com/)",
1512
"publishConfig": {
1613
"access": "public"
1714
},
1815
"dependencies": {
19-
"@pipedream/platform": "^1.2.0"
16+
"@pipedream/platform": "^3.0.3",
17+
"bottleneck": "^2.19.5",
18+
"md5": "^2.3.0"
2019
}
2120
}
Lines changed: 65 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import opensea from "../../opensea.app.mjs";
22
import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform";
3+
import md5 from "md5";
34

45
export default {
5-
name: "New Collection Events",
6-
version: "0.0.3",
76
key: "opensea-new-collection-events",
8-
description:
9-
"Emit new filtered events. [See docs](https://docs.opensea.io/reference/retrieving-asset-events)",
10-
dedupe: "greatest",
7+
name: "New Collection Events",
8+
description: "Emit new filtered events for a collection. [See the documentation](https://docs.opensea.io/reference/list_events_by_collection)",
9+
version: "0.0.4",
10+
dedupe: "unique",
1111
type: "source",
1212
props: {
1313
opensea,
@@ -18,54 +18,81 @@ export default {
1818
intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
1919
},
2020
},
21-
contractAddress: {
21+
collectionSlug: {
2222
type: "string",
23-
label: "Contract Address",
24-
description: "Collection contract address",
23+
label: "Collection Slug",
24+
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.",
2525
},
2626
eventType: {
2727
type: "string",
2828
options: [
29-
"sales",
30-
"listings",
29+
"all",
30+
"cancel",
31+
"listing",
32+
"offer",
33+
"order",
34+
"redemption",
35+
"sale",
36+
"transfer",
3137
],
3238
label: "Event Type",
33-
description: "OpenSea event type",
39+
description: "The type of event to filter by",
40+
default: "all",
41+
optional: true,
3442
},
3543
},
3644
methods: {
37-
getLastTimestamp() {
45+
_getLastTimestamp() {
3846
return this.db.get("lastTimestamp");
3947
},
40-
setLastTimestamp(ts) {
48+
_setLastTimestamp(ts) {
4149
this.db.set("lastTimestamp", ts);
4250
},
43-
},
44-
async run() {
45-
const eventType = this.eventType === "sales"
46-
? "successful"
47-
: "created";
48-
const lastTimestamp = this.getLastTimestamp();
49-
let cursor = null;
50-
do {
51-
const resp = await this.opensea.retrieveEvents({
52-
contract: this.contractAddress,
53-
eventType,
54-
occurredAfter: lastTimestamp,
55-
cursor,
56-
});
57-
resp.asset_events.forEach((event) => {
58-
this.$emit(event, {
59-
id: event.id,
60-
summary: `${event.asset.name} ${this.eventType} event`,
61-
ts: +new Date(event.created_date),
51+
generateMeta(event) {
52+
return {
53+
id: md5(JSON.stringify(event)),
54+
summary: `New ${event.event_type} event`,
55+
ts: event.event_timestamp,
56+
};
57+
},
58+
async processEvent(max) {
59+
const lastTimestamp = this._getLastTimestamp();
60+
let next = null;
61+
let events = [];
62+
do {
63+
const resp = await this.opensea.retrieveEvents({
64+
collectionSlug: this.collectionSlug,
65+
params: {
66+
event_type: this.eventType,
67+
after: lastTimestamp,
68+
next,
69+
},
6270
});
63-
});
64-
if (!cursor && resp.asset_events.length > 0) {
65-
const ts = Math.floor(new Date(resp.asset_events[0].created_date).getTime() / 1000);
66-
this.setLastTimestamp(ts);
71+
if (!resp?.asset_events) {
72+
break;
73+
}
74+
events.push(...resp.asset_events);
75+
next = resp.next;
76+
} while (lastTimestamp && next);
77+
78+
if (!events.length) {
79+
return;
6780
}
68-
cursor = resp.next;
69-
} while (lastTimestamp && cursor);
81+
this._setLastTimestamp(events[0].event_timestamp);
82+
if (max) {
83+
events = events.slice(0, max);
84+
}
85+
events.reverse().forEach((event) => {
86+
this.$emit(event, this.generateMeta(event));
87+
});
88+
},
89+
},
90+
hooks: {
91+
async deploy() {
92+
await this.processEvent(25);
93+
},
94+
},
95+
async run() {
96+
await this.processEvent();
7097
},
7198
};

pnpm-lock.yaml

Lines changed: 12 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)