-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathnft-rpc-strategy.ts
More file actions
120 lines (107 loc) · 3.52 KB
/
nft-rpc-strategy.ts
File metadata and controls
120 lines (107 loc) · 3.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import { ContractData } from '../types.js'
import * as RequestModel from './request-model.js'
import { Effect, RequestResolver } from 'effect'
import { PublicClient } from '../public-client.js'
import { erc721Abi, getContract } from 'viem'
import { ERC1155InterfaceId, ERC721InterfaceId, erc165Abi } from './constants.js'
export const NFTRPCStrategyResolver = (publicClientLive: PublicClient): RequestModel.ContractMetaResolverStrategy => ({
id: 'nft-rpc-strategy',
resolver: RequestResolver.fromEffect(({ chainId, address }: RequestModel.GetContractMetaStrategy) =>
Effect.gen(function* () {
const service = yield* PublicClient
const { client } = yield* service.getPublicClient(chainId)
// const proxyResult = yield* getProxyStorageSlot({ address, chainID })
// const { address: implementationAddress } = proxyResult ?? {}
const contractAddress = address
const inst = getContract({
abi: erc165Abi,
address: contractAddress,
client,
})
const fail = new RequestModel.ResolveStrategyMetaError('NFTRPCStrategy', contractAddress, chainId)
const [isERC721, isERC1155] = yield* Effect.all(
[
Effect.tryPromise({
try: () => inst.read.supportsInterface([ERC721InterfaceId]),
catch: () => fail,
}),
Effect.tryPromise({
try: () => inst.read.supportsInterface([ERC1155InterfaceId]),
catch: () => fail,
}),
],
{
concurrency: 'inherit',
batching: 'inherit',
},
)
if (!isERC721 && !isERC1155) {
// Contract exists but doesn't support NFT interfaces - this is a "no data found" case
return yield* Effect.fail(
new RequestModel.MissingMetaError(
address,
chainId,
'nft-rpc-strategy',
'Contract is not an NFT (ERC721/ERC1155)',
),
)
}
let meta: ContractData | undefined
if (isERC721) {
const erc721inst = getContract({
abi: erc721Abi,
address: contractAddress,
client,
})
const [name, symbol] = yield* Effect.all(
[
Effect.tryPromise({
try: () => erc721inst.read.name(),
catch: () => fail,
}),
Effect.tryPromise({
try: () => erc721inst.read.symbol(),
catch: () => fail,
}),
],
{
concurrency: 'inherit',
batching: 'inherit',
},
)
meta = {
address,
contractAddress: address,
contractName: name,
tokenSymbol: symbol,
type: 'ERC721',
chainID: chainId,
}
}
if (isERC1155) {
meta = {
address,
contractAddress: address,
type: 'ERC1155',
chainID: chainId,
}
}
if (!meta) {
// Contract exists but doesn't support NFT interfaces - this is a "no data found" case
return yield* Effect.fail(
new RequestModel.MissingMetaError(
address,
chainId,
'nft-rpc-strategy',
'Contract is not an NFT (ERC721/ERC1155)',
),
)
}
return meta
}).pipe(Effect.withSpan('MetaStrategy.NFTRPCStrategyResolver', { attributes: { chainId, address } })),
).pipe(
RequestResolver.contextFromServices(PublicClient),
Effect.provideService(PublicClient, publicClientLive),
Effect.runSync,
),
})