Ethers.js

使用大量 Ethers.js 事件偵聽器優化後端

  • October 2, 2022

我一直在建構一個 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中,但您可以使用任何您喜歡的方法。

引用自:https://ethereum.stackexchange.com/questions/136714