From ca95728ac54e31e13588eb94e235ffba75781a84 Mon Sep 17 00:00:00 2001 From: Vanessa Rodriguez Cristobal Date: Tue, 10 Oct 2023 10:30:57 +0100 Subject: [PATCH 1/3] feat(projection): add helper to especifically store UTXO's with assets --- .../src/operators/Mappers/withUtxo.ts | 14 +++++ .../test/operators/Mappers/withUtxo.test.ts | 62 +++++++++++++++++-- 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/packages/projection/src/operators/Mappers/withUtxo.ts b/packages/projection/src/operators/Mappers/withUtxo.ts index 57976b59773..037faa39539 100644 --- a/packages/projection/src/operators/Mappers/withUtxo.ts +++ b/packages/projection/src/operators/Mappers/withUtxo.ts @@ -48,6 +48,20 @@ export const filterProducedUtxoByAddresses = })) ); +export const filterProducedUtxoByAssetsPresence = + (): ProjectionOperator => + // eslint-disable-next-line unicorn/consistent-function-scoping + (evt$) => + evt$.pipe( + map((evt) => ({ + ...evt, + utxo: { + ...evt.utxo, + produced: evt.utxo.produced.filter(([_, { value }]) => value.assets && value.assets.size > 0) + } + })) + ); + export const filterProducedUtxoByAssetPolicyId = ({ policyIds }: FilterByPolicyIds): ProjectionOperator => (evt$) => diff --git a/packages/projection/test/operators/Mappers/withUtxo.test.ts b/packages/projection/test/operators/Mappers/withUtxo.test.ts index 4908082fa2d..98234ddb86d 100644 --- a/packages/projection/test/operators/Mappers/withUtxo.test.ts +++ b/packages/projection/test/operators/Mappers/withUtxo.test.ts @@ -3,6 +3,7 @@ import { ProjectionEvent } from '../../../src'; import { filterProducedUtxoByAddresses, filterProducedUtxoByAssetPolicyId, + filterProducedUtxoByAssetsPresence, withUtxo } from '../../../src/operators/Mappers'; import { firstValueFrom, of } from 'rxjs'; @@ -71,6 +72,43 @@ export const validTxSource$ = of({ ] }, inputSource: Cardano.InputSource.inputs + }, + { + body: { + inputs: [ + { + index: 0, + txId: '73e26ff267b5ee32d8e413635f4f4c9547db1c2af1694faf51be20b9f508b8f6' + } + ], + outputs: [ + { + address: + 'addr_test1qzrf8t56qhzcp2chrtn7deqhep0dttr3eemhnut6lth3gulj7cuplfarmnq5fyumgl0lklddvau9dhamaexykljzvpyswqt56p', + value: { + assets: new Map([ + [ + Cardano.AssetId( + '8f78a4388b1a3e1a1435257e9356fa0c2cc0d3a5999d63b5886c96435365636f6e6454657374746f6b656e' + ), + 1n + ], + [Cardano.AssetId('8f78a4388b1a3e1a1435257e9356fa0c2cc0d3a5999d63b5886c964354657374746f6b656e'), 1n], + [Cardano.AssetId('7f78a4388b1a3e1a1435257e9356fa0c2cc0d3a5999d63b5886c964354657374746f6b656e'), 1n] + ]), + coins: 25_485_292n + } + }, + { + address: 'addr_test1vptwv4jvaqt635jvthpa29lww3vkzypm8l6vk4lv4tqfhhgajdgwf', + value: { + assets: new Map(), + coins: 74_341_815n + } + } + ] + }, + inputSource: Cardano.InputSource.inputs } ] } @@ -172,8 +210,8 @@ describe('withUtxo', () => { const { utxo: { consumed, produced } } = await firstValueFrom(validTxSource$.pipe(withUtxo())); - expect(consumed).toHaveLength(3); - expect(produced).toHaveLength(3); + expect(consumed).toHaveLength(4); + expect(produced).toHaveLength(5); }); it('when inputSource is collateral: maps consumed/produced utxo from collateral/collateralReturn', async () => { @@ -203,7 +241,23 @@ describe('withUtxo', () => { ) ); - expect(produced).toHaveLength(1); + expect(produced).toHaveLength(2); + }); + }); + + describe('filterProducedUtxoByAssetsPresence', () => { + it('keeps only utxo produced that contain any assets', async () => { + const { + utxo: { produced } + } = await firstValueFrom(validTxSource$.pipe(withUtxo(), filterProducedUtxoByAssetsPresence())); + + const utxosWithAssets = produced.filter(([_key, { value }]) => value.assets && value.assets.size > 0); + + expect(utxosWithAssets.length).toBe(produced.length); + + for (const [_key, { value }] of utxosWithAssets) { + expect(value.assets?.size).toBeGreaterThan(0); + } }); }); @@ -220,7 +274,7 @@ describe('withUtxo', () => { ) ); - expect(produced).toHaveLength(1); + expect(produced).toHaveLength(2); expect(produced[0][1].value.assets?.size).toBe(2); }); }); From 129dd353d3831850b451f2ba75d7cd33d0a0d09b Mon Sep 17 00:00:00 2001 From: Vanessa Rodriguez Cristobal Date: Tue, 10 Oct 2023 10:32:04 +0100 Subject: [PATCH 2/3] feat(cardano-services): add Asset projection to prepareTypeOrmProjection --- .../src/Projection/prepareTypeormProjection.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/cardano-services/src/Projection/prepareTypeormProjection.ts b/packages/cardano-services/src/Projection/prepareTypeormProjection.ts index 40d4a9ea3ff..5b6dd74e6b5 100644 --- a/packages/cardano-services/src/Projection/prepareTypeormProjection.ts +++ b/packages/cardano-services/src/Projection/prepareTypeormProjection.ts @@ -40,6 +40,7 @@ import { passthrough } from '@cardano-sdk/util-rxjs'; * */ export enum ProjectionName { + Asset = 'asset', Handle = 'handle', StakePool = 'stake-pool', StakePoolMetadataJob = 'stake-pool-metadata-job', @@ -65,6 +66,10 @@ const createMapperOperators = ( const filterUtxo = applyUtxoAndMintFilters ? Mapper.filterProducedUtxoByAssetPolicyId({ policyIds: handlePolicyIds }) : passthrough(); + const filterProducedUtxoByAssetsPresence = + projectionNames.includes(ProjectionName.Asset) && !projectionNames.includes(ProjectionName.UTXO) + ? Mapper.filterProducedUtxoByAssetsPresence() + : passthrough(); const filterMint = applyUtxoAndMintFilters ? Mapper.filterMintByPolicyIds({ policyIds: handlePolicyIds }) : passthrough(); @@ -74,6 +79,7 @@ const createMapperOperators = ( : passthrough(); return { filterMint, + filterProducedUtxoByAssetsPresence, filterUtxo, withAddresses: Mapper.withAddresses(), withCIP67: Mapper.withCIP67(), @@ -218,6 +224,7 @@ const storeInterDependencies: Partial> = { const projectionStoreDependencies: Record = { address: ['storeAddresses'], + asset: ['storeAssets'], // TODO: remove storeNftMetadata when TypeormAssetProvider tests // are updated to use 'asset' database instead of a handle database handle: ['storeHandles', 'storeHandleMetadata', 'storeNftMetadata'], From f0cf66b944cd4db959be9e431dfc540051d53d9e Mon Sep 17 00:00:00 2001 From: Vanessa Rodriguez Cristobal Date: Tue, 10 Oct 2023 10:32:50 +0100 Subject: [PATCH 3/3] feat: adds Asset projector and provider to docker compose infrastructure --- compose/common.yml | 41 +++++++++++++++++++ compose/dev.yml | 8 ++++ compose/placeholder-secrets/postgres_db_asset | 1 + packages/e2e/docker-compose.yml | 7 ++++ 4 files changed, 57 insertions(+) create mode 100644 compose/placeholder-secrets/postgres_db_asset diff --git a/compose/common.yml b/compose/common.yml index af879b85fae..08e9552a3c0 100644 --- a/compose/common.yml +++ b/compose/common.yml @@ -40,6 +40,7 @@ x-with-postgres: &with-postgres - postgres_password - postgres_user - postgres_db + - postgres_db_asset - postgres_db_db_sync - postgres_db_handle - postgres_db_stake_pool @@ -69,6 +70,7 @@ x-provider-server-environment: &provider-server-environment x-sdk-environment: &sdk-environment LOGGER_MIN_SEVERITY: ${LOGGER_MIN_SEVERITY:-info} OGMIOS_URL: ws://cardano-node-ogmios:1337 + POSTGRES_DB_FILE_ASSET: /run/secrets/postgres_db_handle POSTGRES_DB_FILE_DB_SYNC: /run/secrets/postgres_db_db_sync POSTGRES_DB_FILE_HANDLE: /run/secrets/postgres_db_handle POSTGRES_DB_FILE_STAKE_POOL: /run/secrets/postgres_db_stake_pool @@ -78,12 +80,14 @@ x-sdk-environment: &sdk-environment POSTGRES_POOL_MAX_DB_SYNC: ${POSTGRES_POOL_MAX:-10} POSTGRES_POOL_MAX_HANDLE: ${POSTGRES_POOL_MAX:-10} POSTGRES_POOL_MAX_STAKE_POOL: ${POSTGRES_POOL_MAX:-10} + POSTGRES_PASSWORD_FILE_ASSET: /run/secrets/postgres_password POSTGRES_PASSWORD_FILE_DB_SYNC: /run/secrets/postgres_password POSTGRES_PASSWORD_FILE_HANDLE: /run/secrets/postgres_password POSTGRES_PASSWORD_FILE_STAKE_POOL: /run/secrets/postgres_password POSTGRES_PORT_DB_SYNC: 5432 POSTGRES_PORT_HANDLE: 5432 POSTGRES_PORT_STAKE_POOL: 5432 + POSTGRES_USER_FILE_ASSET: /run/secrets/postgres_user POSTGRES_USER_FILE_DB_SYNC: /run/secrets/postgres_user POSTGRES_USER_FILE_HANDLE: /run/secrets/postgres_user POSTGRES_USER_FILE_STAKE_POOL: /run/secrets/postgres_user @@ -192,6 +196,27 @@ services: - postgres_user shm_size: '2gb' + asset-projector: + <<: + - *from-sdk + - *logging + - *projector + - *with-postgres + environment: + <<: + - *projector-environment + - *sdk-environment + POSTGRES_DB_FILE: /run/secrets/postgres_db_asset + PROJECTION_NAMES: asset + healthcheck: + test: + [ + 'CMD-SHELL', + 'test `curl -fs http://localhost:3000/v1.0.0/health | jq -r ".services[0].projectedTip.blockNo"` -gt 1' + ] + ports: + - ${ASSET_PROJECTOR_PORT:-4006}:3000 + handle-projector: <<: - *from-sdk @@ -262,6 +287,20 @@ services: ports: - ${STAKE_POOL_API_PORT:-4010}:3000 + asset-provider-server: + <<: + - *from-sdk + - *logging + - *provider-server + - *with-postgres + environment: + <<: + - *sdk-environment + - *provider-server-environment + SERVICE_NAMES: asset + ports: + - ${HANDLE_API_PORT:-4014}:3000 + handle-provider-server: <<: - *from-sdk @@ -321,6 +360,8 @@ secrets: # See https://github.com/input-output-hk/cardano-db-sync/blob/aed18d1be192bd58d054cdba23758b579dae9f4e/nix/docker.nix#L116 postgres_db: file: ../../compose/placeholder-secrets/postgres_db_db_sync + postgres_db_asset: + file: ../../compose/placeholder-secrets/postgres_db_asset postgres_db_db_sync: file: ../../compose/placeholder-secrets/postgres_db_db_sync postgres_db_handle: diff --git a/compose/dev.yml b/compose/dev.yml index 25b1b8d4a86..f8ec4f01792 100644 --- a/compose/dev.yml +++ b/compose/dev.yml @@ -1,6 +1,14 @@ version: '3.9' services: + asset-projector: + volumes: + - ../..:/app + + asset-provider-server: + volumes: + - ../..:/app + pg-boss-worker: volumes: - ../..:/app diff --git a/compose/placeholder-secrets/postgres_db_asset b/compose/placeholder-secrets/postgres_db_asset new file mode 100644 index 00000000000..a95e94f6604 --- /dev/null +++ b/compose/placeholder-secrets/postgres_db_asset @@ -0,0 +1 @@ +asset \ No newline at end of file diff --git a/packages/e2e/docker-compose.yml b/packages/e2e/docker-compose.yml index 18e3df2177f..5de1ed17bbe 100644 --- a/packages/e2e/docker-compose.yml +++ b/packages/e2e/docker-compose.yml @@ -79,6 +79,13 @@ services: - ./local-network/config/network:/config - sdk-ipc:/sdk-ipc + asset-provider-server: + environment: + HANDLE_POLICY_IDS_FILE: /sdk-ipc/handle_policy_ids + volumes: + - ./local-network/config/network:/config + - sdk-ipc:/sdk-ipc + volumes: sdk-ipc: driver: local