1
- import { ChainSyncEventType } from "@cardano-sdk/core" ;
2
- import { CredentialEntity , typeormOperator } from "../../dist/esm" ;
3
- import { uniq } from "lodash" ;
4
- import { Mappers } from "@cardano-sdk/projection" ;
1
+ import { Cardano , ChainSyncEventType , TxBodyCBOR } from '@cardano-sdk/core' ;
2
+ import { Hash28ByteBase16 } from '@cardano-sdk/crypto' ;
3
+ import { Mappers } from '@cardano-sdk/projection' ;
4
+ import { credentialsFromAddress } from '@cardano-sdk/projection/src/operators/Mappers/util' ;
5
+ import { CredentialEntity , CredentialType , OutputEntity } from '../entity' ;
6
+ import { typeormOperator } from './util' ;
5
7
6
8
export const storeCredentials = typeormOperator < Mappers . WithUtxo & Mappers . WithAddresses > ( async ( evt ) => {
7
9
const {
@@ -12,17 +14,65 @@ export const storeCredentials = typeormOperator<Mappers.WithUtxo & Mappers.WithA
12
14
13
15
// produced credentials will be automatically deleted via block cascade
14
16
if ( txs . length === 0 || eventType !== ChainSyncEventType . RollForward ) return ;
15
-
16
- const involvedOutputCredentials = uniq ( evt . utxo . produced . map ( ( [ _ , txOut ] ) => txOut . address ) . map ( ( address ) => {
17
- const credential = credentialsFromAddress ( address ) ;
18
- return {
19
- spendingHash : credential . spendingCredentialHash ,
20
- stakeHash : credential . stakeCredential ,
21
- transactions : [ ] // FIXME
22
- } as CredentialEntity ;
23
- } ) )
24
-
25
- // TODO: compute involvedInputCredentials from HyrdratedTxIn addresses
26
- // TODO: compute involved credentials by merging uniq(input + output) credentials
27
- // TODO: reference transactions
28
- } ) ;
17
+
18
+ const utxoRepository = queryRunner . manager . getRepository ( OutputEntity ) ;
19
+ const txIdToCredentials = new Map < Cardano . TransactionId , Map < Hash28ByteBase16 , CredentialType > > ( ) ;
20
+
21
+ const addCredential = (
22
+ { paymentCredentialHash, stakeCredential } : Mappers . Address ,
23
+ map : Map < Hash28ByteBase16 , CredentialType >
24
+ ) => {
25
+ if ( paymentCredentialHash ) {
26
+ map . set ( paymentCredentialHash , CredentialType . PAYMENT ) ;
27
+ }
28
+ if ( stakeCredential && ! ( 'slot' in stakeCredential ) ) {
29
+ // FIXME: Support pointer stake credentials
30
+ map . set ( stakeCredential , CredentialType . STAKE ) ;
31
+ }
32
+ } ;
33
+
34
+ // get input & output credentials by tx
35
+ for ( const tx of evt . block . body ) {
36
+ const txCredentials = new Map < Hash28ByteBase16 , CredentialType > ( ) ;
37
+
38
+ // get tx input address
39
+ const txInOutputs = await Promise . all (
40
+ tx . body . inputs . map (
41
+ async ( { txId, index : outputIndex } ) =>
42
+ await utxoRepository . findOne ( { select : { address : true } , where : { outputIndex, txId } } )
43
+ )
44
+ ) ;
45
+
46
+ // add tx input credentials to involved tx credentials
47
+ for ( const txOut of txInOutputs ) {
48
+ if ( txOut && txOut . address ) {
49
+ addCredential ( credentialsFromAddress ( txOut . address ) , txCredentials ) ;
50
+ }
51
+ }
52
+
53
+ // add tx output credentials to involved tx credentials
54
+ for ( const txOut of tx . body . outputs ) {
55
+ addCredential ( credentialsFromAddress ( txOut . address ) , txCredentials ) ;
56
+ }
57
+
58
+ const credentialEntities = Array . from ( txCredentials ) . map (
59
+ ( [ credentialHash , credentialType ] ) : CredentialEntity => ( {
60
+ credentialHash : Buffer . from ( credentialHash , 'hex' ) ,
61
+ credentialType
62
+ } )
63
+ ) ;
64
+
65
+ await queryRunner . manager
66
+ . createQueryBuilder ( )
67
+ . insert ( )
68
+ . into ( CredentialEntity )
69
+ . values ( credentialEntities )
70
+ . orIgnore ( )
71
+ . execute ( ) ;
72
+
73
+ // store tx credentials for transaction entities
74
+ txIdToCredentials . set ( tx . id , txCredentials ) ;
75
+ }
76
+
77
+ return { txIdToCredentials } ;
78
+ } ) ;
0 commit comments