Ethers.js
使用大量 Ethers.js 事件偵聽器優化後端
我一直在建構一個 nft 市場後端,在管理所有許可的 nft 集合的經理契約之上。這個想法是,經理可以通過這個經理合約創建 erc721 或 erc1155 合約,使用者最初可以通過經理合約鑄造這些代幣。除此之外,轉賬和其他功能都是相同的,並且在代幣合約本身內。現在,我一直在建構一個帶有 mongodb 的 Nest.js 後端,以跟踪所有者、出價、收藏、價格和 uri。到目前為止一切順利,我的堆棧中沒有任何錯誤,但是,我不確定我建構事件偵聽器的方法。我用 provider.on(filter, _) 創建了一個事件監聽器,一旦經理契約創建了一個新集合,就會觸發這個事件。一旦觸發此事件,後端發出一個自定義事件來為集合本身創建新的事件偵聽器 :) 在這一點上有點奇怪,雖然它正在工作,但我擔心一旦有超過 100 個集合,它將是巨大的負載。這意味著將有 100 個合約和事件監聽器。
這是我遵循的方法,任何建議,或者如果這是正確的方法,歡迎批准。感謝您閱讀這篇彌撒 :)
mongo 中有 2 個集合。1是跟踪經理契約產生的集合。另一個是跟踪每個集合 nfts 的 nfts。這部分為經理安裝偵聽器,並在經理髮出新契約後觸發自定義事件
@Resolver() export class ManagerListener implements OnApplicationBootstrap { provider; filter; constructor( private readonly managerService: ManagerService, private eventEmitter: EventEmitter2, ) { this.provider = getRpcProvider(); this.filter = { //manager address address: '0x7C705A6fMOCKDATA32BF4507D0', topics: [ethers.utils.id('NewCollection(address,uint8)')], }; } //manager listener mounts once the server is started onApplicationBootstrap() { this.provider.on(this.filter, async (log, _) => { console.log('new collection deployed at: ', dataToAddress(log.data)); const address = dataToAddress(log.data); const newCollection: ManagerCreateInput = { address }; //this pushes new collection to mongo just as an address. await this.managerService.createManager(newCollection); //this part fires a custom event with the new collection address. this will be //listened by the below part const collectionCreatedEvent = new CollectionCreatedEvent(); collectionCreatedEvent.address = address; this.eventEmitter.emit('collection.created', collectionCreatedEvent); }); } }
另一方面,這部分正在偵聽自定義事件,一旦發出,它就會為 nft 合約本身安裝一個新的 ethers 事件偵聽器。這可能最終會出現在 100 個事件監聽器中,不知道如何擴展這個
@Resolver() export class NFTsListener { provider; filter; constructor(private readonly nftsService: NFTsService) { this.provider = getRpcProvider(); } //erc721 listener //receives the custom event fired by the above code @OnEvent('collection.created') handleCollectionCreatedEvent(payload: CollectionCreatedEvent) { this.filter = { address: payload.address, topics: [ethers.utils.id('Transfer(address,address,uint256)')], }; //mounts a new ethers event for the contract that is deployed by the manager this.provider.on(this.filter, (log, _) => { const newNft: NFTCreateInput = { address: log.address, owner: logToAddress(log.topics[2]), uri: 'MOCKDATA', id: parseInt(log.topics[3]), }; //this pushes a new nft to mongodb return this.nftsService.createOrUpdateNft(newNft); }); } }
我可能會為所有 NFT 使用單個偵聽器。然後通過檢查
log.address
,您可以過濾掉壞的。例如第一部分:
onApplicationBootstrap() { this.provider.on(this.filter, async (log, _) => { console.log('new collection deployed at: ', dataToAddress(log.data)); const address = dataToAddress(log.data); const newCollection: ManagerCreateInput = { address }; //this pushes new collection to mongo just as an address. await this.managerService.createManager(newCollection); myCollections.push(address); }); }
第二部分:
filter = { topics: [ethers.utils.id('Transfer(address,address,uint256)')], }; provider.on(filter, (log, _) => { // exit early if it's not our NFT if (! myCollections.includes(log.address)) return; const newNft: NFTCreateInput = { address: log.address, owner: logToAddress(log.topics[2]), uri: 'MOCKDATA', id: parseInt(log.topics[3]), }; //this pushes a new nft to mongodb return this.nftsService.createOrUpdateNft(newNft); });
所有 NFT 地址都保存在一個數組
myCollections
中,但您可以使用任何您喜歡的方法。