Overview
OpenSea is a leading NFT Marketplace. As with most NFT Marketplaces, OpenSea is non-custodial. As such, all marketplace sales can be seen directly on-chain. This makes it easy to get alerted for sales activity via QuickAlerts.
In this example, we will monitor all sales activity, which could be a useful approach for anyone creating an index without the need of the OpenSea API. The expression could easily be modified to capture sales from a specific seller address, buyer address, collection, token ID or more.
OpenSea's on-chain activity is executed through their Seaport smart contract, which you can read more about in their documentation.
OpenSea NFT Sales
The Seaport smart contract emits an event called OrderFulfilled
when a sale is completed. We can use this event to capture sales activity for a specific NFT Collection. There are currently three versions of the Seaport smart contract in use v1.1, v1.4, and v1.5. Fortunately for us, all three versions emit the same OrderFulfilled
event when a sale is made, making the expression less complex.
To create our expression, we will need to target two values:
- The Seaport contract address(es) - This value is consistent across all chains the contracts are deployed to, with the exception that not all versions are deployed on all chains. You can find the full list of contract deployments by chain on the Seaport GitHub readme. As we're looking for transaction logs that come from these contracts, we'll then filter down by them as the
tx_logs_address
value. - The event the contract emits when the action we're interested in occurs - As mentioned above, across all 3 versions currently in use, we are interested in the
OrderFulfilled
event (event documentation from OpenSea). On EVM blockchains, the event is encoded and can be found intx_logs_topic0
. To get the encoded value, you will need to take the event definition (event name and parameters' types), run it through the Keccak-256 hash function, and prefix it with0x
.
OrderFulfilled(bytes32,address,address,address,(uint8,address,uint256,uint256)[],(uint8,address,uint256,uint256,address)[])
⬇
9d9af8e38d66c62e2c12f0225249fd9d721c54b83f48d9352c97c6cacdcb6f31
⬇
0x9d9af8e38d66c62e2c12f0225249fd9d721c54b83f48d9352c97c6cacdcb6f31
1tx_logs_address in (2'0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC',3'0x00000000000001ad428e4906aE43D8F9852d0dD6',4'0x00000000006c3852cbEf3e08E8dF289169EdE581'5)6&&7tx_logs_topic0 == '0x9d9af8e38d66c62e2c12f0225249fd9d721c54b83f48d9352c97c6cacdcb6f31'