From 603a25f26abf08525f86f607056420759f12a7f6 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Fri, 24 Jun 2022 10:06:44 +0300 Subject: [PATCH] Tracking transfer event & updating nft owner (#436) * Adding Tranfer eventHandler to subgraph.template.yaml * Started adding transfer event to mapping * updating getNftTokenWithID function * Pulling from Origin v4main * Removing console.log * Updating token Utils * Updating newOwner with User & writting new test * Updating test * Ensuring account is in lowercase * Creating seperate test for transfering an NFT query * Updating test name * Removing console.logs * Moviving transfer event tracking from factory to template * Moving handleNftTransferred to nftUpdate mapping * Adding logging * Using correct token address * Fix linting * Checking the correct owner account has been set originally --- scripts/generatenetworkssubgraphs.js | 4 +- src/mappings/nftUpdate.ts | 15 +++- src/mappings/utils/tokenUtils.ts | 14 +++ subgraph.template.yaml | 2 + test/integration/SimplePublishConsume.test.ts | 89 +++++++++++++++++++ 5 files changed, 120 insertions(+), 4 deletions(-) diff --git a/scripts/generatenetworkssubgraphs.js b/scripts/generatenetworkssubgraphs.js index 3f0b559..0e8e343 100644 --- a/scripts/generatenetworkssubgraphs.js +++ b/scripts/generatenetworkssubgraphs.js @@ -1,6 +1,6 @@ /* eslint-disable no-unused-vars */ -var fs = require('fs') -var addresses = require('@oceanprotocol/contracts/addresses/address.json') +const fs = require('fs') +let addresses = require('@oceanprotocol/contracts/addresses/address.json') async function replaceContractAddresses() { // load addresses file first diff --git a/src/mappings/nftUpdate.ts b/src/mappings/nftUpdate.ts index 7fb2ad4..a04801d 100644 --- a/src/mappings/nftUpdate.ts +++ b/src/mappings/nftUpdate.ts @@ -12,10 +12,12 @@ import { RemovedFromCreateERC20List, RemovedFromMetadataList, RemovedManager, - CleanedPermissions + CleanedPermissions, + Transfer } from '../@types/templates/ERC721Template/ERC721Template' import { NftUpdateType } from './utils/constants' -import { getNftToken } from './utils/tokenUtils' +import { getNftToken, getNftTokenWithID } from './utils/tokenUtils' +import { getUser } from './utils/userUtils' function getId(tx: string, nftAddress: string): string { return `${tx}-${nftAddress}` @@ -247,3 +249,12 @@ export function handleCleanedPermissions(event: CleanedPermissions): void { nft.managerRole = newList nft.save() } + +export function handleNftTransferred(event: Transfer): void { + const id = event.address.toHex() + const nft = getNftTokenWithID(id) + const newOwner = getUser(event.params.to.toHexString()) + nft.owner = newOwner.id + + nft.save() +} diff --git a/src/mappings/utils/tokenUtils.ts b/src/mappings/utils/tokenUtils.ts index f0d56dc..925f81c 100644 --- a/src/mappings/utils/tokenUtils.ts +++ b/src/mappings/utils/tokenUtils.ts @@ -60,6 +60,20 @@ export function getNftToken(address: Address): Nft { return newToken } +export function getNftTokenWithID(tokenId: string): Nft { + let nftToken = Nft.load(tokenId) + if (nftToken === null) { + nftToken = new Nft(tokenId) + // const contract = ERC721Template.bind(address) + nftToken.name = '' + nftToken.symbol = '' + nftToken.address = tokenId + nftToken.save() + addNft() + } + return nftToken +} + export function getUSDValue( address: string, value: BigDecimal, diff --git a/subgraph.template.yaml b/subgraph.template.yaml index ddc1fd4..1e961e0 100644 --- a/subgraph.template.yaml +++ b/subgraph.template.yaml @@ -197,6 +197,8 @@ templates: handler: handleRemovedManager - event: CleanedPermissions(indexed address,uint256,uint256) handler: handleCleanedPermissions + - event: Transfer(indexed address,indexed address,indexed uint256) + handler: handleNftTransferred - name: Dispenser kind: ethereum/contract diff --git a/test/integration/SimplePublishConsume.test.ts b/test/integration/SimplePublishConsume.test.ts index ce737e2..973269c 100644 --- a/test/integration/SimplePublishConsume.test.ts +++ b/test/integration/SimplePublishConsume.test.ts @@ -192,4 +192,93 @@ describe('Simple Publish & consume test', async () => { } */ }) + it('should publish and transfer an NFT', async () => { + const nft = new Nft(web3) + const Factory = new NftFactory(addresses.ERC721Factory, web3) + const accounts = await web3.eth.getAccounts() + const publisherAccount = accounts[0] + const newOwnerAccount = accounts[1].toLowerCase() + + const nftParams: NftCreateData = { + name: 'testNFT', + symbol: 'TST', + templateIndex: 1, + tokenURI: '', + transferable: true, + owner: publisherAccount + } + const erc20Params: Erc20CreateParams = { + templateIndex: 1, + cap: '100000', + feeAmount: '0', + paymentCollector: '0x0000000000000000000000000000000000000000', + feeToken: '0x0000000000000000000000000000000000000000', + minter: publisherAccount, + mpFeeAddress: '0x0000000000000000000000000000000000000000' + } + const result = await Factory.createNftWithErc20( + publisherAccount, + nftParams, + erc20Params + ) + await sleep(2000) + const erc721Address = result.events.NFTCreated.returnValues[0] + const datatokenAddress = result.events.TokenCreated.returnValues[0] + const graphNftToken = erc721Address.toLowerCase() + + const queryOriginalOwner = { + query: `query { + nft(id:"${graphNftToken}"){symbol,id,owner}}` + } + const initialResponse = await fetch(subgraphUrl, { + method: 'POST', + body: JSON.stringify(queryOriginalOwner) + }) + const initialResult = await initialResponse.json() + // Checking original owner account has been set correctly + assert( + initialResult.data.nft.owner.toLowerCase() === + publisherAccount.toLowerCase() + ) + + // create the files encrypted string + let providerResponse = await ProviderInstance.encrypt(assetUrl, providerUrl) + ddo.services[0].files = await providerResponse + ddo.services[0].datatokenAddress = datatokenAddress + // update ddo and set the right did + ddo.nftAddress = erc721Address + const chain = await web3.eth.getChainId() + ddo.id = + 'did:op:' + + SHA256(web3.utils.toChecksumAddress(erc721Address) + chain.toString(10)) + + providerResponse = await ProviderInstance.encrypt(ddo, providerUrl) + const encryptedResponse = await providerResponse + const metadataHash = getHash(JSON.stringify(ddo)) + await nft.setMetadata( + erc721Address, + publisherAccount, + 0, + providerUrl, + '', + '0x2', + encryptedResponse, + '0x' + metadataHash + ) + await sleep(2000) + + // Transfer the NFT + await nft.transferNft(graphNftToken, publisherAccount, newOwnerAccount) + await sleep(2000) + const query2 = { + query: `query { + nft(id:"${graphNftToken}"){symbol,id,owner, transferable}}` + } + const response = await fetch(subgraphUrl, { + method: 'POST', + body: JSON.stringify(query2) + }) + const queryResult = await response.json() + assert(queryResult.data.nft.owner === newOwnerAccount) + }) })