Skip to content

Commit 9b28880

Browse files
authored
fix: allow multiple sft mints for the same token per transaction (#279)
* fix: allow multiple sft mints for the same token per transaction * test: sft * fix: forof
1 parent ec5aef9 commit 9b28880

File tree

2 files changed

+28
-8
lines changed

2 files changed

+28
-8
lines changed

src/pg/chainhook/chainhook-pg-store.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,10 @@ import { StacksEvent, StacksPayload } from '@hirosystems/chainhook-client';
99
import { ENV } from '../../env';
1010
import {
1111
NftMintEvent,
12-
SftMintEvent,
1312
SmartContractDeployment,
1413
TokenMetadataUpdateNotification,
1514
} from '../../token-processor/util/sip-validation';
16-
import { ContractNotFoundError } from '../errors';
17-
import { DbJob, DbSipNumber, DbSmartContractInsert, DbTokenType, DbSmartContract } from '../types';
15+
import { DbSmartContractInsert, DbTokenType, DbSmartContract } from '../types';
1816
import { BlockCache, CachedEvent } from './block-cache';
1917
import { dbSipNumberToDbTokenType } from '../../token-processor/util/helpers';
2018
import BigNumber from 'bignumber.js';
@@ -322,25 +320,30 @@ export class ChainhookPgStore extends BasePgStoreModule {
322320
): Promise<void> {
323321
if (mints.length == 0) return;
324322
for await (const batch of batchIterate(mints, 500)) {
325-
const values = batch.map(m => {
323+
const tokenValues = new Map<string, (string | number)[]>();
324+
for (const m of batch) {
325+
// SFT tokens may mint one single token more than once given that it's an FT within an NFT.
326+
// This makes sure we only keep the first occurrence.
327+
const tokenKey = `${m.event.contractId}-${m.event.tokenId}`;
328+
if (tokenValues.has(tokenKey)) continue;
326329
logger.info(
327330
`ChainhookPgStore apply ${tokenType.toUpperCase()} mint ${m.event.contractId} (${
328331
m.event.tokenId
329332
}) at block ${cache.block.index}`
330333
);
331-
return [
334+
tokenValues.set(tokenKey, [
332335
m.event.contractId,
333336
tokenType,
334337
m.event.tokenId.toString(),
335338
cache.block.index,
336339
cache.block.hash,
337340
m.tx_id,
338341
m.tx_index,
339-
];
340-
});
342+
]);
343+
}
341344
await sql`
342345
WITH insert_values (principal, type, token_number, block_height, index_block_hash, tx_id,
343-
tx_index) AS (VALUES ${sql(values)}),
346+
tx_index) AS (VALUES ${sql([...tokenValues.values()])}),
344347
filtered_values AS (
345348
SELECT s.id AS smart_contract_id, i.type::token_type, i.token_number::bigint,
346349
i.block_height::bigint, i.index_block_hash::text, i.tx_id::text, i.tx_index::int

tests/chainhook/sft-events.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,23 @@ describe('SFT events', () => {
5252
),
5353
},
5454
})
55+
// Try a duplicate of the same token but different amount
56+
.event({
57+
type: 'SmartContractEvent',
58+
position: { index: 1 },
59+
data: {
60+
contract_identifier: contractId,
61+
topic: 'print',
62+
raw_value: cvToHex(
63+
tupleCV({
64+
type: bufferCV(Buffer.from('sft_mint')),
65+
recipient: bufferCV(Buffer.from(address)),
66+
'token-id': uintCV(3),
67+
amount: uintCV(200),
68+
})
69+
),
70+
},
71+
})
5572
.build()
5673
);
5774

0 commit comments

Comments
 (0)