Skip to content

Commit

Permalink
Merge pull request #24 from Once-Upon/feat/split-cryptopunks
Browse files Browse the repository at this point in the history
feat: split cryptopunks from old nfts
  • Loading branch information
pcowgill authored Mar 4, 2024
2 parents 0289227 + 13b7bb5 commit 99be4f8
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 89 deletions.
8 changes: 6 additions & 2 deletions src/helpers/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -403,8 +403,6 @@ export const EXECUTE_TRANSACTION_SIGNATURE =
'execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)';

export const OLD_NFT_ADDRESSES = [
'0x6ba6f2207e343923ba692e5cae646fb0f566db8d', // CRYPTOPUNKS_OLD
'0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb', // CRYPTOPUNKS_NEW
'0x06012c8cf97bead5deae237070f9587f8e7a266d', // CryptoKitties
'0xe897e5953ef250bd49875fe7a48254def92730b9', // FanBits
'0x73b0ebea28f76be1368d578d13657354330472a9', // XART
Expand All @@ -416,6 +414,12 @@ export const OLD_NFT_ADDRESSES = [
'0x323a3e1693e7a0959f65972f3bf2dfcb93239dfe', // Digital Art Chain
'0x552d72f86f04098a4eaeda6d7b665ac12f846ad2', // Dark Winds
];

export const CRYPTO_PUNKS_ADDRESSES = [
'0x6ba6f2207e343923ba692e5cae646fb0f566db8d', // CRYPTOPUNKS_OLD
'0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb', // CRYPTOPUNKS_NEW
];

export const ERC721_TRANSFER_EVENT_1 = [
{
anonymous: false,
Expand Down
71 changes: 71 additions & 0 deletions src/transformers/ethereum/assetTransfersCryptopunks.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { transform as transactionAssetTransfers } from '../_common/assetTransfers';
import { transform } from './assetTransfersCryptopunks';
import { loadBlockFixture } from '../../helpers/utils';

describe('transactionAssetTransfersCryptopunks', () => {
it('should return transaction asset transfers CryptoPunks', () => {
// Special NFT transfers
/** CryptoPunks New */
const cryptoPunksNewBlock = loadBlockFixture('ethereum', 5774644);
const cryptoPunksNewAssetResult =
transactionAssetTransfers(cryptoPunksNewBlock);
const cryptoPunksNewResult = transform(cryptoPunksNewAssetResult);
const cryptoPunksNewTx = cryptoPunksNewResult.transactions.find(
(tx) =>
tx.hash ===
'0x0da4c50900119b47400d71a9dd3563571145e4e362b952c36a9e38c77f7d25bb',
);
expect(cryptoPunksNewTx).toBeDefined();
if (cryptoPunksNewTx) {
const cryptoPunksNewTransfers = cryptoPunksNewTx.assetTransfers;
expect(cryptoPunksNewTransfers[0].type).toBe('erc721');
if ('tokenId' in cryptoPunksNewTransfers[0]) {
expect(cryptoPunksNewTransfers[0].tokenId).toBe('89');
}
}
/** CryptoPunks Old */
const cryptoPunksOldBlock = loadBlockFixture('ethereum', 3862484);
const cryptoPunksOldAssetResult =
transactionAssetTransfers(cryptoPunksOldBlock);
const cryptoPunksOldResult = transform(cryptoPunksOldAssetResult);
const cryptoPunksOldTx = cryptoPunksOldResult.transactions.find(
(tx) =>
tx.hash ===
'0xff75a6739be926fe7328167011b5e2ac6a8883f55e76af70410520ef7b115901',
);
expect(cryptoPunksOldTx).toBeDefined();
if (cryptoPunksOldTx) {
const cryptoPunksOldTransfers = cryptoPunksOldTx.assetTransfers;
expect(cryptoPunksOldTransfers[0].type).toBe('erc721');
if ('tokenId' in cryptoPunksOldTransfers[0]) {
expect(cryptoPunksOldTransfers[0].tokenId).toBe('4851');
}
}
});

it('should return asset transfers for CryptoPunks transactions', () => {
const cryptoPunksBlock = loadBlockFixture('ethereum', '19321357_decoded');
const cryptoPunksAssetResult = transactionAssetTransfers(cryptoPunksBlock);
const cryptoPunksResult = transform(cryptoPunksAssetResult);
const cryptoPunksTx = cryptoPunksResult.transactions.find(
(tx) =>
tx.hash ===
'0x4b581466cca3f2b50a6b97c053dd207feb911c6f858f21331ff829aa97dc6159',
);
expect(cryptoPunksTx).toBeDefined();
if (cryptoPunksTx) {
const cryptoPunksTransfers = cryptoPunksTx.assetTransfers;
expect(cryptoPunksTransfers.length).toBe(1);
if ('tokenId' in cryptoPunksTransfers[0]) {
expect(cryptoPunksTransfers[0].tokenId).toBe('7071');
expect(cryptoPunksTransfers[0].from).toBe(
'0x4e6d2af4931681a024da8feaa4faba2bf8bbdc65',
);
expect(cryptoPunksTransfers[0].to).toBe(
'0x1919db36ca2fa2e15f9000fd9cdc2edcf863e685',
);
}
expect(cryptoPunksTransfers[0].type).toBe('erc721');
}
});
});
78 changes: 78 additions & 0 deletions src/transformers/ethereum/assetTransfersCryptopunks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { decodeEVMAddress } from '../../helpers/utils';
import {
AssetType,
type AssetTransfer,
type RawBlock,
type RawTransaction,
} from '../../types';
import { CRYPTO_PUNKS_ADDRESSES } from '../../helpers/constants';

const TRANSFER_SIGNATURES = {
// event PunkTransfer(address indexed from, address indexed to, uint256 punkIndex)
CRYPTO_PUNKS_ERC721:
'0x05af636b70da6819000c49f85b21fa82081c632069bb626f30932034099107d8',
// event PunkBought(uint indexed punkIndex, uint value, address indexed fromAddress, address indexed toAddress)
CRYPTO_PUNKS_ERC721_BUY:
'0x58e5d5a525e3b40bc15abaa38b5882678db1ee68befd2f60bafe3a7fd06db9e3',
};

function updateTokenTransfers(tx: RawTransaction) {
const cryptopunksTransfers: AssetTransfer[] = [];

for (const log of tx.receipt.logs) {
if (!CRYPTO_PUNKS_ADDRESSES.includes(log.address)) {
continue;
}

const [signature] = log.topics;

switch (signature) {
case TRANSFER_SIGNATURES.CRYPTO_PUNKS_ERC721:
cryptopunksTransfers.push({
asset: log.address,
from: decodeEVMAddress(log.topics[1]),
to: decodeEVMAddress(log.topics[2]),
tokenId: BigInt(log.data).toString(),
type: AssetType.ERC721,
});
break;
case TRANSFER_SIGNATURES.CRYPTO_PUNKS_ERC721_BUY:
cryptopunksTransfers.push({
asset: log.address,
from: decodeEVMAddress(log.topics[2]),
to: decodeEVMAddress(log.topics[3]),
tokenId: BigInt(log.topics[1]).toString(),
type: AssetType.ERC721,
});
break;
default:
break;
}
}

// filter old asset transfers from previous asset transfers
const nonOldAssetTransfers = tx.assetTransfers.filter(
(assetTransfer) =>
assetTransfer.type !== AssetType.ETH &&
!CRYPTO_PUNKS_ADDRESSES.includes(assetTransfer.asset),
);
const assetTransfers = [...nonOldAssetTransfers, ...cryptopunksTransfers];

return assetTransfers;
}

export function transform(block: RawBlock): RawBlock {
block.transactions = block.transactions.map((tx) => {
const hasCryptopunksTransfer = tx.assetTransfers?.some(
(assetTransfer) =>
assetTransfer.type !== AssetType.ETH &&
CRYPTO_PUNKS_ADDRESSES.includes(assetTransfer.asset),
);
if (hasCryptopunksTransfer) {
tx.assetTransfers = updateTokenTransfers(tx);
}
return tx;
});

return block;
}
63 changes: 1 addition & 62 deletions src/transformers/ethereum/assetTransfersOldNFTs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,42 +24,7 @@ describe('transactionAssetTransfersOldNFTs', () => {
}
expect(cryptoKittiesTransfers[0].type).toBe('erc721');
}
/** CryptoPunks New */
const cryptoPunksNewBlock = loadBlockFixture('ethereum', 5774644);
const cryptoPunksNewAssetResult =
transactionAssetTransfers(cryptoPunksNewBlock);
const cryptoPunksNewResult = transform(cryptoPunksNewAssetResult);
const cryptoPunksNewTx = cryptoPunksNewResult.transactions.find(
(tx) =>
tx.hash ===
'0x0da4c50900119b47400d71a9dd3563571145e4e362b952c36a9e38c77f7d25bb',
);
expect(cryptoPunksNewTx).toBeDefined();
if (cryptoPunksNewTx) {
const cryptoPunksNewTransfers = cryptoPunksNewTx.assetTransfers;
expect(cryptoPunksNewTransfers[0].type).toBe('erc721');
if ('tokenId' in cryptoPunksNewTransfers[0]) {
expect(cryptoPunksNewTransfers[0].tokenId).toBe('89');
}
}
/** CryptoPunks Old */
const cryptoPunksOldBlock = loadBlockFixture('ethereum', 3862484);
const cryptoPunksOldAssetResult =
transactionAssetTransfers(cryptoPunksOldBlock);
const cryptoPunksOldResult = transform(cryptoPunksOldAssetResult);
const cryptoPunksOldTx = cryptoPunksOldResult.transactions.find(
(tx) =>
tx.hash ===
'0xff75a6739be926fe7328167011b5e2ac6a8883f55e76af70410520ef7b115901',
);
expect(cryptoPunksOldTx).toBeDefined();
if (cryptoPunksOldTx) {
const cryptoPunksOldTransfers = cryptoPunksOldTx.assetTransfers;
expect(cryptoPunksOldTransfers[0].type).toBe('erc721');
if ('tokenId' in cryptoPunksOldTransfers[0]) {
expect(cryptoPunksOldTransfers[0].tokenId).toBe('4851');
}
}

/** CryptoStriker */
const cryptoStrikersBlock = loadBlockFixture('ethereum', 15685187);
const cryptoStrikersAssetResult =
Expand Down Expand Up @@ -154,30 +119,4 @@ describe('transactionAssetTransfersOldNFTs', () => {
expect(cryptoKittiesTransfers[0].type).toBe('erc721');
}
});

it('should return asset transfers for CryptoPunks transactions', () => {
const cryptoPunksBlock = loadBlockFixture('ethereum', '19321357_decoded');
const cryptoPunksAssetResult = transactionAssetTransfers(cryptoPunksBlock);
const cryptoPunksResult = transform(cryptoPunksAssetResult);
const cryptoPunksTx = cryptoPunksResult.transactions.find(
(tx) =>
tx.hash ===
'0x4b581466cca3f2b50a6b97c053dd207feb911c6f858f21331ff829aa97dc6159',
);
expect(cryptoPunksTx).toBeDefined();
if (cryptoPunksTx) {
const cryptoPunksTransfers = cryptoPunksTx.assetTransfers;
expect(cryptoPunksTransfers.length).toBe(1);
if ('tokenId' in cryptoPunksTransfers[0]) {
expect(cryptoPunksTransfers[0].tokenId).toBe('7071');
expect(cryptoPunksTransfers[0].from).toBe(
'0x4e6d2af4931681a024da8feaa4faba2bf8bbdc65',
);
expect(cryptoPunksTransfers[0].to).toBe(
'0x1919db36ca2fa2e15f9000fd9cdc2edcf863e685',
);
}
expect(cryptoPunksTransfers[0].type).toBe('erc721');
}
});
});
25 changes: 0 additions & 25 deletions src/transformers/ethereum/assetTransfersOldNFTs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,6 @@ import { decodeEventLog, Hex } from 'viem';
const TRANSFER_SIGNATURES = {
// event Transfer(address,address,uint256)
ERC721: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',

// event PunkTransfer(address indexed from, address indexed to, uint256 punkIndex)
CRYPTO_PUNKS_ERC721:
'0x05af636b70da6819000c49f85b21fa82081c632069bb626f30932034099107d8',
// event PunkBought(uint indexed punkIndex, uint value, address indexed fromAddress, address indexed toAddress)
CRYPTO_PUNKS_ERC721_BUY:
'0x58e5d5a525e3b40bc15abaa38b5882678db1ee68befd2f60bafe3a7fd06db9e3',
};

function updateTokenTransfers(tx: RawTransaction) {
Expand Down Expand Up @@ -96,24 +89,6 @@ function updateTokenTransfers(tx: RawTransaction) {
}
}

break;
case TRANSFER_SIGNATURES.CRYPTO_PUNKS_ERC721:
oldNFTsTransfers.push({
asset: log.address,
from: decodeEVMAddress(log.topics[1]),
to: decodeEVMAddress(log.topics[2]),
tokenId: BigInt(log.data).toString(),
type: AssetType.ERC721,
});
break;
case TRANSFER_SIGNATURES.CRYPTO_PUNKS_ERC721_BUY:
oldNFTsTransfers.push({
asset: log.address,
from: decodeEVMAddress(log.topics[2]),
to: decodeEVMAddress(log.topics[3]),
tokenId: BigInt(log.topics[1]).toString(),
type: AssetType.ERC721,
});
break;
default:
break;
Expand Down
2 changes: 2 additions & 0 deletions src/transformers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ import * as transactionParties from './_common/parties';
import * as transactionSigHash from './_common/sigHash';
import * as transactionTimestamp from './_common/timestamp';
import * as transactionAssetTransfersOldNFTs from './ethereum/assetTransfersOldNFTs';
import * as transactionAssetTransfersCryptopunks from './ethereum/assetTransfersCryptopunks';
import * as transactionFees from './ethereum/fees';
import * as transactionForks from './ethereum/forks';

const children = {
transactionAssetTransfers,
transactionAssetTransfersOldNFTs,
transactionAssetTransfersCryptopunks,
transactionDelegateCalls,
transactionDerivativesNeighbors,
transactionErrors,
Expand Down

0 comments on commit 99be4f8

Please sign in to comment.