Skip to content

Commit 2cd1e01

Browse files
Merge pull request #1077 from input-output-hk/feat/lw-9678-resolve-collateral-return-property
feat(cardano-services): resolve collateralReturn property
2 parents 170253c + d1286b7 commit 2cd1e01

File tree

10 files changed

+79
-24
lines changed

10 files changed

+79
-24
lines changed

packages/cardano-services/src/ChainHistory/DbSyncChainHistory/ChainHistoryBuilder.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export class ChainHistoryBuilder {
5151
public async queryTransactionInputsByIds(ids: string[], collateral = false): Promise<TxInput[]> {
5252
this.#logger.debug(`About to find inputs (collateral: ${collateral}) for transactions with ids:`, ids);
5353
const result: QueryResult<TxInputModel> = await this.#db.query({
54-
name: `tx_${collateral ? 'collateral' : 'inputs'}_by_tx_ids`,
54+
name: `tx_${collateral ? 'collateral_' : ''}inputs_by_tx_ids`,
5555
text: collateral ? Queries.findTxCollateralsByIds : Queries.findTxInputsByIds,
5656
values: [ids]
5757
});
@@ -68,11 +68,11 @@ export class ChainHistoryBuilder {
6868
return mapTxOutTokenMap(result.rows);
6969
}
7070

71-
public async queryTransactionOutputsByIds(ids: string[]): Promise<TxOutput[]> {
72-
this.#logger.debug('About to find outputs for transactions with ids:', ids);
71+
public async queryTransactionOutputsByIds(ids: string[], collateral = false): Promise<TxOutput[]> {
72+
this.#logger.debug(`About to find outputs (collateral: ${collateral}) for transactions with ids:`, ids);
7373
const result: QueryResult<TxOutputModel> = await this.#db.query({
74-
name: 'tx_outputs_by_tx_ids',
75-
text: Queries.findTxOutputsByIds,
74+
name: `tx_${collateral ? 'collateral_' : ''}outputs_by_tx_ids`,
75+
text: collateral ? Queries.findCollateralOutputsByTxIds : Queries.findTxOutputsByIds,
7676
values: [ids]
7777
});
7878
if (result.rows.length === 0) return [];

packages/cardano-services/src/ChainHistory/DbSyncChainHistory/DbSyncChainHistoryProvider.ts

+17-11
Original file line numberDiff line numberDiff line change
@@ -107,29 +107,35 @@ export class DbSyncChainHistoryProvider extends DbSyncProvider() implements Chai
107107
});
108108
if (txResults.rows.length === 0) return [];
109109

110-
const [inputs, outputs, mints, withdrawals, redeemers, metadata, collaterals, certificates] = await Promise.all([
111-
this.#builder.queryTransactionInputsByIds(ids),
112-
this.#builder.queryTransactionOutputsByIds(ids),
113-
this.#builder.queryTxMintByIds(ids),
114-
this.#builder.queryWithdrawalsByTxIds(ids),
115-
this.#builder.queryRedeemersByIds(ids),
116-
// Missing witness datums
117-
this.#metadataService.queryTxMetadataByRecordIds(ids),
118-
this.#builder.queryTransactionInputsByIds(ids, true),
119-
this.#builder.queryCertificatesByIds(ids)
120-
]);
110+
const [inputs, outputs, mints, withdrawals, redeemers, metadata, collaterals, certificates, collateralOutputs] =
111+
await Promise.all([
112+
this.#builder.queryTransactionInputsByIds(ids),
113+
this.#builder.queryTransactionOutputsByIds(ids),
114+
this.#builder.queryTxMintByIds(ids),
115+
this.#builder.queryWithdrawalsByTxIds(ids),
116+
this.#builder.queryRedeemersByIds(ids),
117+
// Missing witness datums
118+
this.#metadataService.queryTxMetadataByRecordIds(ids),
119+
this.#builder.queryTransactionInputsByIds(ids, true),
120+
this.#builder.queryCertificatesByIds(ids),
121+
this.#builder.queryTransactionOutputsByIds(ids, true)
122+
]);
121123

122124
return txResults.rows.map((tx) => {
123125
const txId = tx.id.toString('hex') as unknown as Cardano.TransactionId;
124126
const txInputs = orderBy(inputs.filter((input) => input.txInputId === txId).map(mapTxIn), ['index']);
125127
const txCollaterals = orderBy(collaterals.filter((col) => col.txInputId === txId).map(mapTxIn), ['index']);
126128
const txOutputs = orderBy(outputs.filter((output) => output.txId === txId).map(mapTxOut), ['index']);
129+
const txCollateralOutputs = orderBy(collateralOutputs.filter((output) => output.txId === txId).map(mapTxOut), [
130+
'index'
131+
]);
127132
const inputSource: Cardano.InputSource = tx.valid_contract
128133
? Cardano.InputSource.inputs
129134
: Cardano.InputSource.collaterals;
130135

131136
return mapTxAlonzo(tx, {
132137
certificates: certificates.get(txId),
138+
collateralOutputs: txCollateralOutputs,
133139
collaterals: txCollaterals,
134140
inputSource,
135141
inputs: txInputs,

packages/cardano-services/src/ChainHistory/DbSyncChainHistory/mappers.ts

+14-1
Original file line numberDiff line numberDiff line change
@@ -185,11 +185,23 @@ interface TxAlonzoData {
185185
metadata?: Cardano.TxMetadata;
186186
collaterals?: Cardano.HydratedTxIn[];
187187
certificates?: Cardano.Certificate[];
188+
collateralOutputs?: Cardano.TxOut[];
188189
}
189190

190191
export const mapTxAlonzo = (
191192
txModel: TxModel,
192-
{ inputSource, inputs, outputs, mint, withdrawals, redeemers, metadata, collaterals, certificates }: TxAlonzoData
193+
{
194+
inputSource,
195+
inputs,
196+
outputs,
197+
mint,
198+
withdrawals,
199+
redeemers,
200+
metadata,
201+
collaterals,
202+
certificates,
203+
collateralOutputs = []
204+
}: TxAlonzoData
193205
): Cardano.HydratedTx => ({
194206
auxiliaryData:
195207
metadata && metadata.size > 0
@@ -204,6 +216,7 @@ export const mapTxAlonzo = (
204216
},
205217
body: {
206218
certificates,
219+
collateralReturn: collateralOutputs.length > 0 ? collateralOutputs[0] : undefined,
207220
collaterals,
208221
fee: BigInt(txModel.fee),
209222
inputs,

packages/cardano-services/src/ChainHistory/DbSyncChainHistory/queries.ts

+9-4
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ const selectTxInput = (collateral?: boolean) => `
1515
JOIN tx AS source_tx
1616
ON tx_out.tx_id = source_tx.id`;
1717

18-
const selectTxOutput = `
18+
const selectTxOutput = (collateral = false) => `
1919
SELECT
2020
tx_out.id AS id,
2121
tx_out.address AS address,
2222
tx_out."index" AS "index",
2323
tx_out.value AS coin_value,
2424
tx_out.data_hash AS datum,
2525
tx.hash AS tx_id
26-
FROM tx_out
26+
FROM ${collateral ? 'collateral_tx_out' : 'tx_out'} AS tx_out
2727
JOIN tx ON tx_out.tx_id = tx.id`;
2828

2929
export const findTxInputsByIds = `
@@ -45,18 +45,23 @@ export const findTxInputsByAddresses = `
4545
ORDER BY tx_in.id ASC`;
4646

4747
export const findTxOutputsByIds = `
48-
${selectTxOutput}
48+
${selectTxOutput()}
4949
WHERE tx.id = ANY($1)
5050
ORDER BY tx_out.id ASC`;
5151

5252
export const findTxOutputsByAddresses = `
53-
${selectTxOutput}
53+
${selectTxOutput()}
5454
JOIN block ON tx.block_id = block.id
5555
WHERE tx_out.address = ANY($1)
5656
AND block.block_no >= $2
5757
AND block.block_no <= $3
5858
ORDER BY tx_out.id ASC`;
5959

60+
export const findCollateralOutputsByTxIds = `
61+
${selectTxOutput(true)}
62+
WHERE tx.id = ANY($1)
63+
ORDER BY tx_out.id ASC`;
64+
6065
export const findTip = `
6166
SELECT
6267
block_no,

packages/cardano-services/test/ChainHistory/ChainHistoryHttpService.test.ts

+10
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,16 @@ describe('ChainHistoryHttpService', () => {
324324
expect(tx.body.collaterals?.length).toEqual(1);
325325
});
326326

327+
it('has collateral outputs', async () => {
328+
const response = await provider.transactionsByHashes({
329+
ids: await fixtureBuilder.getTxHashes(1, { with: [TxWith.CollateralOutput] })
330+
});
331+
const tx: Cardano.HydratedTx = response[0];
332+
expect(response.length).toEqual(1);
333+
334+
expect(tx.body.collateralReturn).toMatchShapeOf(DataMocks.Tx.collateralReturn);
335+
});
336+
327337
it('has certificates', async () => {
328338
const response = await provider.transactionsByHashes({
329339
ids: await fixtureBuilder.getTxHashes(2, { with: [TxWith.DelegationCertificate] })

packages/cardano-services/test/ChainHistory/DbSyncChainHistoryProvider/ChainHistoryBuilder.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ describe('ChainHistoryBuilder', () => {
101101
const result = await builder.queryTransactionOutputsByIds(ids);
102102
expect(result.length).toBeGreaterThanOrEqual(2);
103103
expect(result[0]).toMatchShapeOf(DataMocks.Tx.txOut);
104-
checkLoggedTxIds('About to find outputs for transactions with ids', true);
104+
checkLoggedTxIds('About to find outputs \\(collateral: false\\) for transactions with ids', true);
105105
});
106106
test('query transaction outputs with empty array', async () => {
107107
const result = await builder.queryTransactionOutputsByIds([]);

packages/cardano-services/test/ChainHistory/DbSyncChainHistoryProvider/mappers.test.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ describe('chain history mappers', () => {
374374
test('map TxModel to Cardano.HydratedTx with extra data', () => {
375375
const result = mappers.mapTxAlonzo(txModel, {
376376
certificates,
377+
collateralOutputs: [txOutput],
377378
collaterals: inputs,
378379
inputSource,
379380
inputs,
@@ -386,7 +387,14 @@ describe('chain history mappers', () => {
386387
expect(result).toEqual<Cardano.HydratedTx>({
387388
...expected,
388389
auxiliaryData: { blob: metadata },
389-
body: { ...expected.body, certificates, collaterals: inputs, mint: assets, withdrawals },
390+
body: {
391+
...expected.body,
392+
certificates,
393+
collateralReturn: txOutput,
394+
collaterals: inputs,
395+
mint: assets,
396+
withdrawals
397+
},
390398
witness: { ...expected.witness, redeemers }
391399
});
392400
});

packages/cardano-services/test/ChainHistory/fixtures/FixtureBuilder.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ export enum TxWith {
1717
Mint = 'mint',
1818
MultiAsset = 'multiAsset',
1919
Redeemer = 'redeemer',
20-
Withdrawal = 'withdrawal'
20+
Withdrawal = 'withdrawal',
21+
CollateralOutput = 'collateralOutput'
2122
}
2223

2324
export type AddressesInBlockRange = {
@@ -120,6 +121,7 @@ export class ChainHistoryFixtureBuilder {
120121
if (options.with.includes(TxWith.DelegationCertificate)) query += Queries.latestTxHashesWithDelegationCerts;
121122
if (options.with.includes(TxWith.MirCertificate)) query += Queries.latestTxHashesWithMirCerts;
122123
if (options.with.includes(TxWith.Withdrawal)) query += Queries.latestTxHashesWithWithdrawal;
124+
if (options.with.includes(TxWith.CollateralOutput)) query += Queries.latestTxHashesWithCollateralOutput;
123125

124126
query += Queries.endLatestTxHashes;
125127
}

packages/cardano-services/test/ChainHistory/fixtures/queries.ts

+4
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ export const latestTxHashesWithMirCerts = `
5757
export const latestTxHashesWithWithdrawal = `
5858
JOIN withdrawal ON withdrawal.tx_id = tx.id`;
5959

60+
export const latestTxHashesWithCollateralOutput = `
61+
JOIN collateral_tx_out ON collateral_tx_out.tx_id = tx.id`;
62+
6063
export const endLatestTxHashes = `
6164
GROUP BY tx.id
6265
ORDER BY tx.id DESC
@@ -101,6 +104,7 @@ const Queries = {
101104
latestTxHashes,
102105
latestTxHashesWithAuxiliaryData,
103106
latestTxHashesWithCollateral,
107+
latestTxHashesWithCollateralOutput,
104108
latestTxHashesWithDelegationCerts,
105109
latestTxHashesWithMint,
106110
latestTxHashesWithMirCerts,

packages/cardano-services/test/data-mocks/tx.ts

+7
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,13 @@ export const collateralInputs = [
114114
}
115115
];
116116

117+
export const collateralReturn: Cardano.TxOut = {
118+
address: Cardano.PaymentAddress('addr_test1wqnp362vmvr8jtc946d3a3utqgclfdl5y9d3kn849e359hst7hkqk'),
119+
value: {
120+
coins: 3_681_817_479_100_950n
121+
}
122+
};
123+
117124
export const withValidityInterval: Cardano.HydratedTx = merge(withAssets, {
118125
body: {
119126
validityInterval: {

0 commit comments

Comments
 (0)