Skip to content

Commit

Permalink
fix(projection): keep track of burned handles
Browse files Browse the repository at this point in the history
  • Loading branch information
mkazlauskas committed May 30, 2023
1 parent fc3af2c commit 7367a8f
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 13 deletions.
36 changes: 28 additions & 8 deletions packages/projection/src/operators/Mappers/withHandles.ts
@@ -1,12 +1,13 @@
import { Asset, Cardano } from '@cardano-sdk/core';
import { FilterByPolicyIds } from './types';
import { ProjectionOperator } from '../../types';
import { WithMint } from './withMint';
import { isNotNil } from '@cardano-sdk/util';
import { map } from 'rxjs';

export interface Handle {
handle: string;
address: Cardano.PaymentAddress;
address: Cardano.PaymentAddress | null;
assetId: Cardano.AssetId;
policyId: Cardano.PolicyId;
datum?: Cardano.Datum;
Expand All @@ -16,13 +17,15 @@ export interface WithHandles {
handles: Handle[];
}

const handleFromAssetId = (assetId: Cardano.AssetId) =>
Buffer.from(Asset.util.assetNameFromAssetId(assetId), 'hex').toString('utf8');

export const withHandles =
<PropsIn>({ policyIds }: FilterByPolicyIds): ProjectionOperator<PropsIn, WithHandles> =>
<PropsIn extends WithMint>({ policyIds }: FilterByPolicyIds): ProjectionOperator<PropsIn, WithHandles> =>
(evt$) =>
evt$.pipe(
map((evt) => ({
...evt,
handles: evt.block.body
map((evt) => {
const outputHandles = evt.block.body
.flatMap(({ body: { outputs } }) =>
outputs.flatMap(({ address, value, datum }) =>
[...(value.assets?.entries() || [])].map(([assetId]): Handle | null => {
Expand All @@ -32,12 +35,29 @@ export const withHandles =
address,
assetId,
datum,
handle: Buffer.from(Asset.util.assetNameFromAssetId(assetId), 'hex').toString('utf8'),
handle: handleFromAssetId(assetId),
policyId
};
})
)
)
.filter(isNotNil)
}))
.filter(isNotNil);
const lostHandles = evt.mint
.filter(
({ policyId, assetId }) =>
policyIds.includes(policyId) && !outputHandles.some((handle) => handle.assetId === assetId)
)
.map(
({ assetId, policyId }): Handle => ({
address: null,
assetId,
handle: handleFromAssetId(assetId),
policyId
})
);
return {
...evt,
handles: [...outputHandles, ...lostHandles]
};
})
);
35 changes: 30 additions & 5 deletions packages/projection/test/operators/Mappers/withHandle.test.ts
@@ -1,7 +1,7 @@
import { Asset, Cardano } from '@cardano-sdk/core';
import { Buffer } from 'buffer';
import { HexBlob } from '@cardano-sdk/util';
import { ProjectionEvent } from '../../../src';
import { Mappers, ProjectionEvent } from '../../../src';
import { firstValueFrom, of } from 'rxjs';
import { withHandles } from '../../../src/operators/Mappers';

Expand All @@ -27,8 +27,9 @@ describe('withHandles', () => {
}
];
const validTxSource$ = of({
block: { body: [{ body: { outputs } }] }
} as ProjectionEvent);
block: { body: [{ body: { outputs } }] },
mint: [] as Mappers.Mint[]
} as ProjectionEvent<Mappers.WithMint>);
const { handles } = await firstValueFrom(
validTxSource$.pipe(
withHandles({
Expand All @@ -40,6 +41,29 @@ describe('withHandles', () => {
expect(handles[0].datum).toEqual(datum);
});

it('includes a handle with "null" address, when transaction burns a handle', async () => {
const validTxSource$ = of({
block: { body: [{ body: { outputs: [] as Cardano.TxOut[] } }] },
mint: [
{
assetId: assetIdFromHandle('bob'),
compactTxId: 123,
policyId: handlePolicyId,
quantity: -1n
}
] as Mappers.Mint[]
} as ProjectionEvent<Mappers.WithMint>);
const { handles } = await firstValueFrom(
validTxSource$.pipe(
withHandles({
policyIds: [handlePolicyId]
})
)
);
expect(handles.length).toBe(1);
expect(handles[0].address).toBeNull();
});

it('maps and filters assets, from outputs, containing handles matching the given policy ID to an array of objects', async () => {
const bobHandleOne = 'bob.handle.one';
const bobHandleTwo = 'bob.handle.two';
Expand Down Expand Up @@ -107,8 +131,9 @@ describe('withHandles', () => {
}
}
]
}
} as ProjectionEvent);
},
mint: [] as Mappers.Mint[]
} as ProjectionEvent<Mappers.WithMint>);

const { handles } = await firstValueFrom(
validTxSource$.pipe(
Expand Down

0 comments on commit 7367a8f

Please sign in to comment.