Skip to content

Commit

Permalink
fix: lint issues; bi-directional relationship
Browse files Browse the repository at this point in the history
  • Loading branch information
will-break-it committed Jul 24, 2024
1 parent 9a6f871 commit 81b1d91
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,9 @@ const willStore: Partial<WillStore> = {
const entities = {
address: AddressEntity,
asset: AssetEntity,
credential: CredentialEntity,
block: BlockEntity,
blockData: BlockDataEntity,
credential: CredentialEntity,
currentPoolMetrics: CurrentPoolMetricsEntity,
handle: HandleEntity,
handleMetadata: HandleMetadataEntity,
Expand Down Expand Up @@ -252,7 +252,7 @@ const mapperInterDependencies: Partial<Record<MapperName, MapperName[]>> = {
withHandles: ['withMint', 'filterMint', 'withUtxo', 'filterUtxo', 'withCIP67'],
withNftMetadata: ['withCIP67', 'withMint', 'filterMint'],
withStakeKeyRegistrations: ['withCertificates'],
withStakePools: ['withCertificates'],
withStakePools: ['withCertificates']
};

const storeMapperDependencies: Partial<Record<StoreName, MapperName[]>> = {
Expand Down
3 changes: 2 additions & 1 deletion packages/projection-typeorm/src/entity/Credential.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ export class CredentialEntity {
transactions?: TransactionEntity[];
}

export const credentialEntityComparator = (c1: CredentialEntity, c2: CredentialEntity) => c1.credentialHash === c2.credentialHash && c1.credentialType === c2.credentialType;
export const credentialEntityComparator = (c1: CredentialEntity, c2: CredentialEntity) =>
c1.credentialHash === c2.credentialHash && c1.credentialType === c2.credentialType;
67 changes: 37 additions & 30 deletions packages/projection-typeorm/src/operators/storeCredentials.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Cardano, ChainSyncEventType } from '@cardano-sdk/core';
import { CredentialEntity, credentialEntityComparator, CredentialType, OutputEntity } from '../entity';
import { CredentialEntity, CredentialType, OutputEntity, credentialEntityComparator } from '../entity';
import { Hash28ByteBase16 } from '@cardano-sdk/crypto';
import { Mappers } from '@cardano-sdk/projection';
import { Repository } from 'typeorm';
import { typeormOperator } from './util';
import { unionWith } from 'lodash';
import uniqWith from 'lodash/uniqWith.js';

export interface WithTxCredentials {
credentialsByTx: Record<Cardano.TransactionId, CredentialEntity[]>;
Expand All @@ -19,15 +19,15 @@ const addInputCredentials = async (
) => {
for (const txHash of Object.keys(utxoByTx) as Cardano.TransactionId[]) {
const txInLookups = utxoByTx[txHash].consumed.map(({ txId, index: outputIndex }) => ({
txId,
outputIndex
outputIndex,
txId
}));

const outputEntities = await utxoRepository.find({
select: { address: true, txId: true, outputIndex: true },
select: { address: true, outputIndex: true, txId: true },
where: txInLookups.map(({ txId, outputIndex }) => ({
txId,
outputIndex
outputIndex,
txId
}))
});

Expand Down Expand Up @@ -70,26 +70,24 @@ const addCertificateCredentials = (
};

type AddressPart = 'payment' | 'stake';
const credentialTypefromAddressType = (type: Cardano.AddressType, part: AddressPart) => {
switch (type) {
case Cardano.AddressType.BasePaymentKeyStakeKey:
case Cardano.AddressType.EnterpriseKey:
return part === 'payment' ? CredentialType.PaymentKey : CredentialType.StakeKey;
case Cardano.AddressType.BasePaymentKeyStakeScript:
return part === 'payment' ? CredentialType.PaymentKey : CredentialType.StakeScript;
case Cardano.AddressType.BasePaymentScriptStakeKey:
return part === 'payment' ? CredentialType.PaymentScript : CredentialType.StakeKey;
case Cardano.AddressType.BasePaymentScriptStakeScript:
case Cardano.AddressType.EnterpriseScript:
return part === 'payment' ? CredentialType.PaymentScript : CredentialType.StakeScript;
case Cardano.AddressType.RewardKey:
return CredentialType.StakeKey;
case Cardano.AddressType.RewardScript:
return CredentialType.StakeScript;
default:
// FIXME: map byron address, pointer script, pointer key type
return null;
}
const credentialTypeMap: { [key: number]: { payment: CredentialType | null; stake: CredentialType } } = {
[Cardano.AddressType.BasePaymentKeyStakeKey]: { payment: CredentialType.PaymentKey, stake: CredentialType.StakeKey },
[Cardano.AddressType.EnterpriseKey]: { payment: CredentialType.PaymentKey, stake: CredentialType.StakeKey },
[Cardano.AddressType.BasePaymentKeyStakeScript]: {
payment: CredentialType.PaymentKey,
stake: CredentialType.StakeScript
},
[Cardano.AddressType.BasePaymentScriptStakeKey]: {
payment: CredentialType.PaymentScript,
stake: CredentialType.StakeKey
},
[Cardano.AddressType.BasePaymentScriptStakeScript]: {
payment: CredentialType.PaymentScript,
stake: CredentialType.StakeScript
},
[Cardano.AddressType.EnterpriseScript]: { payment: CredentialType.PaymentScript, stake: CredentialType.StakeScript },
[Cardano.AddressType.RewardKey]: { payment: null, stake: CredentialType.StakeKey },
[Cardano.AddressType.RewardScript]: { payment: null, stake: CredentialType.StakeScript }
};

export const storeCredentials = typeormOperator<
Expand Down Expand Up @@ -119,20 +117,29 @@ export const storeCredentials = typeormOperator<
) =>
txToCredentials.set(
txId,
unionWith([...(txToCredentials.get(txId) || []), { credentialHash, credentialType }], credentialEntityComparator)
uniqWith([...(txToCredentials.get(txId) || []), { credentialHash, credentialType }], credentialEntityComparator)
);

const credentialTypeFromAddressType = (type: Cardano.AddressType, part: AddressPart) => {
const credential = credentialTypeMap[type];
if (!credential) {
// FIXME: map byron address, pointer script, pointer key type
return null;
}
return credential[part];
};

const addCredentialFromAddress = (
txId: Cardano.TransactionId,
{ paymentCredentialHash, stakeCredential, type }: Mappers.Address
) => {
const paymentCredentialType = credentialTypefromAddressType(type, 'payment');
const paymentCredentialType = credentialTypeFromAddressType(type, 'payment');
if (paymentCredentialHash && paymentCredentialType) {
addCredential(txId, paymentCredentialHash, paymentCredentialType);
}

if (stakeCredential) {
const stakeCredentialType = credentialTypefromAddressType(type, 'stake');
const stakeCredentialType = credentialTypeFromAddressType(type, 'stake');
// FIXME: support pointers
if (stakeCredentialType && typeof stakeCredential === 'string') {
addCredential(txId, stakeCredential, stakeCredentialType);
Expand Down
10 changes: 5 additions & 5 deletions packages/projection-typeorm/src/operators/storeTransactions.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { ChainSyncEventType } from '@cardano-sdk/core';
import { CredentialEntity, TransactionEntity } from '../entity';
import { WithBlock } from '@cardano-sdk/projection';
import { WithTxCredentials } from './storeCredentials';
import { typeormOperator } from './util';
import { WithBlock } from '@cardano-sdk/projection';

export const willStoreTransactions = ({ block: { body } }: WithBlock) => body.length > 0;

Expand All @@ -28,13 +28,13 @@ export const storeTransactions = typeormOperator<WithTxCredentials>(async (evt)
txId: tx.id
};
transactionEntities.push(txEntity);
credentials.forEach((credential) => {
for (const credential of credentials) {
if (!credential.transactions) {
credential.transactions = [];
}
credential.transactions.push(txEntity);
credentialEntities.add(credential); // Collect credentials to be re-saved
});
}
}

await queryRunner.manager
Expand All @@ -44,7 +44,7 @@ export const storeTransactions = typeormOperator<WithTxCredentials>(async (evt)
.values(transactionEntities)
.orIgnore()
.execute();

// Re-save credential entities to ensure relationships are persisted
await queryRunner.manager.save(Array.from(credentialEntities));
await queryRunner.manager.save([...credentialEntities]);
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Cardano } from '@cardano-sdk/core';
import { unifiedProjectorOperator } from '../../utils';
import { uniqWith } from 'lodash';
import uniqWith from 'lodash/uniqWith.js';

export interface OnChainCertificate {
pointer: Cardano.Pointer;
Expand All @@ -15,7 +15,8 @@ export interface WithCertificates {
const isNotPhase2ValidationErrorTx = (tx: Cardano.OnChainTx<Cardano.TxBody>) =>
!Cardano.util.isPhase2ValidationErrTx(tx);

const credentialComparator = (c1: Cardano.Credential, c2: Cardano.Credential) => c1.hash === c2.hash && c1.type === c2.type;
const credentialComparator = (c1: Cardano.Credential, c2: Cardano.Credential) =>
c1.hash === c2.hash && c1.type === c2.type;

/** Adds flat array of certificates to event as well as a record of stake credentials grouped by transaction id. */
export const withCertificates = unifiedProjectorOperator<{}, WithCertificates>((evt) => {
Expand All @@ -29,7 +30,10 @@ export const withCertificates = unifiedProjectorOperator<{}, WithCertificates>((
const txs = body.filter(isNotPhase2ValidationErrorTx);

const addCredential = (txId: Cardano.TransactionId, credential: Cardano.Credential) =>
txToStakeCredentials.set(txId, uniqWith([...(txToStakeCredentials.get(txId) || []), credential], credentialComparator));
txToStakeCredentials.set(
txId,
uniqWith([...(txToStakeCredentials.get(txId) || []), credential], credentialComparator)
);

for (const [
txIndex,
Expand Down

0 comments on commit 81b1d91

Please sign in to comment.