Skip to content

Commit 70b86f7

Browse files
committed
fix: Fetch Contributable Worlds
1 parent d28f3a9 commit 70b86f7

File tree

4 files changed

+381
-138
lines changed

4 files changed

+381
-138
lines changed

packages/renderer/src/lib/ens.ts

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
import { type ChainId } from '@dcl/schemas/dist/dapps/chain-id';
2+
import { isDev } from '../modules/store/ens/utils';
3+
4+
const BATCH_SIZE = 1000;
5+
6+
export type Domain = { name: string };
7+
export type DomainsQueryResult = { data: { domains: Domain[] } } | { errors: any };
8+
9+
export type OwnerByENSTuple = {
10+
name: string;
11+
wrappedOwner: {
12+
id: string;
13+
};
14+
};
15+
export type OwnerByENSQueryResult =
16+
| {
17+
data: {
18+
domains: OwnerByENSTuple[];
19+
};
20+
}
21+
| { errors: any };
22+
23+
export class ENS {
24+
private subgraph = 'https://subgraph.decentraland.org/ens';
25+
constructor(chainId: ChainId) {
26+
if (isDev(chainId)) {
27+
this.subgraph = 'https://subgraph.decentraland.org/ens-sepolia';
28+
}
29+
}
30+
31+
public async fetchNames(address: string) {
32+
const response: Response = await fetch(this.subgraph, {
33+
method: 'POST',
34+
body: JSON.stringify({
35+
query: `{
36+
domains(
37+
where: {or: [
38+
{ wrappedOwner: "${address.toLowerCase()}" },
39+
{ registrant: "${address.toLowerCase()}" }
40+
]}
41+
) {
42+
name
43+
}
44+
}`,
45+
}),
46+
});
47+
48+
if (!response.ok) {
49+
throw new Error(response.status.toString());
50+
}
51+
52+
const queryResult: DomainsQueryResult = await response.json();
53+
54+
if ('errors' in queryResult) {
55+
throw new Error(JSON.stringify(queryResult.errors));
56+
}
57+
58+
return queryResult.data.domains.map(domain => domain.name);
59+
}
60+
61+
public async fetchNamesOwners(domains: string[]): Promise<Record<string, string>> {
62+
if (!domains) {
63+
return {};
64+
}
65+
66+
const response: Response = await fetch(this.subgraph, {
67+
method: 'POST',
68+
body: JSON.stringify({
69+
query: `query getOwners($domains: [String]) {
70+
domains(where: { name_in: $domains }) {
71+
name
72+
wrappedOwner {
73+
id
74+
}
75+
}
76+
}`,
77+
variables: { domains },
78+
}),
79+
});
80+
81+
if (!response.ok) {
82+
throw new Error(response.status.toString());
83+
}
84+
85+
const queryResult: OwnerByENSQueryResult = await response.json();
86+
87+
if ('errors' in queryResult) {
88+
throw new Error(JSON.stringify(queryResult.errors));
89+
}
90+
91+
const results: Record<string, string> = {};
92+
queryResult.data.domains.forEach(({ wrappedOwner, name }) => {
93+
results[name] = wrappedOwner.id;
94+
});
95+
return results;
96+
}
97+
}
98+
99+
export type DCLDomainsQueryResult =
100+
| { data: { nfts: { ens: { subdomain: string } }[] } }
101+
| { errors: any };
102+
103+
export type DCLOwnerByNameTuple = {
104+
owner: {
105+
address: string;
106+
};
107+
ens: {
108+
subdomain: string;
109+
};
110+
};
111+
export type DCLOwnerByNameQueryResult = {
112+
data: {
113+
nfts: DCLOwnerByNameTuple[];
114+
};
115+
};
116+
117+
export class DCLNames {
118+
private subgraph = 'https://subgraph.decentraland.org/marketplace';
119+
constructor(chainId: ChainId) {
120+
if (isDev(chainId)) {
121+
this.subgraph = 'https://subgraph.decentraland.org/marketplace-sepolia';
122+
}
123+
}
124+
125+
public async fetchNames(address: string) {
126+
let results: string[] = [];
127+
let offset = 0;
128+
let nextPage = true;
129+
130+
while (nextPage) {
131+
const response: Response = await fetch(this.subgraph, {
132+
method: 'POST',
133+
body: JSON.stringify({
134+
query: `{
135+
nfts(
136+
first: ${BATCH_SIZE},
137+
skip: ${offset},
138+
where: {
139+
owner_: { id: "${address.toLowerCase()}" },
140+
category: ens
141+
}
142+
) {
143+
ens {
144+
subdomain
145+
}
146+
}
147+
}`,
148+
}),
149+
});
150+
151+
if (!response.ok) {
152+
throw new Error(response.status.toString());
153+
}
154+
155+
const queryResult: DCLDomainsQueryResult = await response.json();
156+
157+
if ('errors' in queryResult) {
158+
throw new Error(JSON.stringify(queryResult.errors));
159+
}
160+
const domains: string[] = queryResult.data.nfts.map(
161+
nft => `${nft.ens.subdomain.toString()}.dcl.eth`,
162+
);
163+
results = results.concat(domains);
164+
165+
if (domains.length === BATCH_SIZE) {
166+
offset += BATCH_SIZE;
167+
} else {
168+
nextPage = false;
169+
}
170+
}
171+
172+
return results;
173+
}
174+
175+
public async fetchNamesOwners(domains: string[]) {
176+
if (!domains) {
177+
return {};
178+
}
179+
180+
const results: Record<string, string> = {};
181+
let offset = 0;
182+
let nextPage = true;
183+
184+
while (nextPage) {
185+
const response: Response = await fetch(this.subgraph, {
186+
method: 'POST',
187+
body: JSON.stringify({
188+
query: `query getOwners($domains: [String!], $offset: Int) {
189+
nfts(first: ${BATCH_SIZE}, skip: $offset, where: { name_in: $domains, category: ens }) {
190+
owner {
191+
address
192+
}
193+
ens {
194+
subdomain
195+
}
196+
}
197+
}`,
198+
variables: { domains, offset },
199+
}),
200+
});
201+
202+
if (!response.ok) {
203+
throw new Error(response.status.toString());
204+
}
205+
206+
const queryResult: DCLOwnerByNameQueryResult = await response.json();
207+
208+
if ('errors' in queryResult) {
209+
throw new Error(JSON.stringify(queryResult.errors));
210+
}
211+
queryResult.data.nfts.forEach(({ ens, owner }) => {
212+
results[ens.subdomain] = owner.address;
213+
});
214+
215+
if (queryResult.data.nfts.length === BATCH_SIZE) {
216+
offset += BATCH_SIZE;
217+
} else {
218+
nextPage = false;
219+
}
220+
}
221+
222+
return results;
223+
}
224+
}

packages/renderer/src/lib/worlds.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import fetch from 'decentraland-crypto-fetch';
22
import type { AuthIdentity } from '@dcl/crypto';
3+
import { localStorageGetIdentity } from '@dcl/single-sign-on-client';
34
import { DEPLOY_URLS } from '/shared/types/deploy';
45

56
import type { ContributableDomain } from '../modules/store/ens/types';
@@ -145,6 +146,14 @@ export class Worlds {
145146
}
146147
}
147148

149+
private withIdentity(address: string): AuthIdentity {
150+
const identity = localStorageGetIdentity(address);
151+
if (!identity) {
152+
throw new Error('No identity found');
153+
}
154+
return identity;
155+
}
156+
148157
public async fetchWorld(name: string) {
149158
try {
150159
const result = await fetch(`${this.url}/entities/active`, {
@@ -187,7 +196,7 @@ export class Worlds {
187196
};
188197

189198
public postPermissionType = async (
190-
identity: AuthIdentity,
199+
address: string,
191200
worldName: string,
192201
worldPermissionNames: WorldPermissionNames,
193202
worldPermissionType: WorldPermissionType,
@@ -199,48 +208,46 @@ export class Worlds {
199208
metadata: {
200209
type: worldPermissionType,
201210
},
202-
identity,
211+
identity: this.withIdentity(address),
203212
},
204213
);
205214
return result.status === 204;
206215
};
207216

208217
public putPermissionType = async (
209-
identity: AuthIdentity,
218+
address: string,
210219
worldName: string,
211220
worldPermissionNames: WorldPermissionNames,
212-
address: string,
213221
) => {
214222
const result = await fetch(
215223
`${this.url}/world/${worldName}/permissions/${worldPermissionNames}/${address}`,
216224
{
217225
method: 'PUT',
218-
identity,
226+
identity: this.withIdentity(address),
219227
},
220228
);
221229
return result.status === 204;
222230
};
223231

224232
public deletePermissionType = async (
225-
identity: AuthIdentity,
233+
address: string,
226234
worldName: string,
227235
worldPermissionNames: WorldPermissionNames,
228-
address: string,
229236
) => {
230237
const result = await fetch(
231238
`${this.url}/world/${worldName}/permissions/${worldPermissionNames}/${address}`,
232239
{
233240
method: 'DELETE',
234-
identity,
241+
identity: this.withIdentity(address),
235242
},
236243
);
237244
return result.status === 204;
238245
};
239246

240-
public fetchContributableDomains = async (identity: AuthIdentity) => {
247+
public fetchContributableDomains = async (address: string) => {
241248
const result = await fetch(`${this.url}/wallet/contribute`, {
242249
method: 'GET',
243-
identity,
250+
identity: this.withIdentity(address),
244251
});
245252

246253
if (result.ok) {

0 commit comments

Comments
 (0)