Skip to content

Commit 22b99f3

Browse files
committed
feature: Add multi-asset metadata to tx_out
1 parent 0b7c281 commit 22b99f3

File tree

8 files changed

+84
-3
lines changed

8 files changed

+84
-3
lines changed

cardano-db-sync/src/Cardano/DbSync/Era/Byron/Genesis.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ insertTxOutsByron syncEnv disInOut blkId (address, value) = do
224224
, C.txOutInlineDatumId = Nothing
225225
, C.txOutReferenceScriptId = Nothing
226226
, C.txOutConsumedByTxId = Nothing
227+
, C.txOutMaTxOut = Nothing
227228
}
228229
DB.TxOutVariantAddress -> do
229230
let addrRaw = serialize' address
@@ -244,6 +245,7 @@ insertTxOutsByron syncEnv disInOut blkId (address, value) = do
244245
, V.txOutAddressId = addrDetailId
245246
, V.txOutConsumedByTxId = Nothing
246247
, V.txOutStakeAddressId = Nothing
248+
, V.txOutMaTxOut = Nothing
247249
}
248250

249251
mkVAddress :: ByteString -> V.Address

cardano-db-sync/src/Cardano/DbSync/Era/Byron/Insert.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ insertTxOutByron syncEnv _hasConsumed bootStrap txId index txout =
363363
, C.txOutReferenceScriptId = Nothing
364364
, C.txOutStakeAddressId = Nothing -- Byron does not have a stake address.
365365
, C.txOutTxId = txId
366+
, C.txOutMaTxOut = Nothing
366367
, C.txOutValue = DbLovelace (Byron.unsafeGetLovelace $ Byron.txOutValue txout)
367368
}
368369
DB.TxOutVariantAddress -> do
@@ -382,6 +383,7 @@ insertTxOutByron syncEnv _hasConsumed bootStrap txId index txout =
382383
, V.txOutInlineDatumId = Nothing
383384
, V.txOutReferenceScriptId = Nothing
384385
, V.txOutTxId = txId
386+
, V.txOutMaTxOut = Nothing
385387
, V.txOutValue = DbLovelace (Byron.unsafeGetLovelace $ Byron.txOutValue txout)
386388
, V.txOutStakeAddressId = Nothing
387389
}

cardano-db-sync/src/Cardano/DbSync/Era/Shelley/Generic/Tx/Types.hs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{-# LANGUAGE FlexibleInstances #-}
22
{-# LANGUAGE LambdaCase #-}
3+
{-# LANGUAGE OverloadedStrings #-}
34
{-# LANGUAGE RankNTypes #-}
5+
{-# LANGUAGE RecordWildCards #-}
46
{-# LANGUAGE UndecidableSuperClasses #-}
57
{-# LANGUAGE NoImplicitPrelude #-}
68

@@ -13,6 +15,7 @@ module Cardano.DbSync.Era.Shelley.Generic.Tx.Types (
1315
TxWithdrawal (..),
1416
TxIn (..),
1517
TxOut (..),
18+
TxOutMultiAsset (..),
1619
TxRedeemer (..),
1720
TxScript (..),
1821
PlutusData (..),
@@ -26,6 +29,7 @@ module Cardano.DbSync.Era.Shelley.Generic.Tx.Types (
2629
getMaybeDatumHash,
2730
sumTxOutCoin,
2831
toTxHash,
32+
fromMultiAssetMap,
2933
) where
3034

3135
import qualified Cardano.Db as DB
@@ -42,12 +46,16 @@ import Cardano.Ledger.Conway.Governance
4246
import Cardano.Ledger.Conway.Scripts
4347
import Cardano.Ledger.Conway.TxCert (ConwayTxCert)
4448
import Cardano.Ledger.Core (TxBody)
45-
import Cardano.Ledger.Mary.Value (AssetName, MultiAsset, PolicyID)
49+
import Cardano.Ledger.Mary.Value (AssetName (..), MultiAsset, PolicyID)
4650
import qualified Cardano.Ledger.Shelley.TxBody as Shelley
4751
import Cardano.Ledger.Shelley.TxCert
4852
import qualified Cardano.Ledger.TxIn as Ledger
4953
import Cardano.Prelude
5054
import Cardano.Slotting.Slot (SlotNo (..))
55+
import Data.Aeson (FromJSON (..), ToJSON (..), (.:), (.=))
56+
import Data.Aeson.Types (object, withObject)
57+
import Data.ByteString.Short (toShort)
58+
import qualified Data.Map as Map
5159
import Ouroboros.Consensus.Cardano.Block (StandardAlonzo, StandardBabbage, StandardConway, StandardCrypto, StandardShelley)
5260

5361
data Tx = Tx
@@ -114,6 +122,13 @@ data TxOut = TxOut
114122
, txOutDatum :: !TxOutDatum
115123
}
116124

125+
data TxOutMultiAsset = TxOutMultiAsset
126+
{ txOutMaPolicyId :: !(PolicyID StandardCrypto)
127+
, txOutMaAssetName :: !AssetName
128+
, txOutMaAmount :: !Integer
129+
}
130+
deriving (Eq, Show)
131+
117132
data TxRedeemer = TxRedeemer
118133
{ txRedeemerMem :: !Word64
119134
, txRedeemerSteps :: !Word64
@@ -151,6 +166,24 @@ data PoolStats = PoolStats
151166
, votingPower :: Maybe Coin
152167
}
153168

169+
instance ToJSON TxOutMultiAsset where
170+
toJSON TxOutMultiAsset {..} =
171+
object
172+
[ "policyId" .= txOutMaPolicyId
173+
, "assetName" .= txOutMaAssetName
174+
, "amount" .= txOutMaAmount
175+
]
176+
177+
instance FromJSON TxOutMultiAsset where
178+
parseJSON = withObject "MultiAsset" $ \o ->
179+
TxOutMultiAsset
180+
<$> o .: "policyId"
181+
<*> (parseAssetName <$> o .: "assetName")
182+
<*> o .: "amount"
183+
where
184+
parseAssetName :: Text -> AssetName
185+
parseAssetName t = AssetName $ toShort (encodeUtf8 t)
186+
154187
toTxCert :: Word16 -> Cert -> TxCertificate
155188
toTxCert idx dcert =
156189
TxCertificate
@@ -172,6 +205,17 @@ getMaybeDatumHash :: Maybe DataHash -> TxOutDatum
172205
getMaybeDatumHash Nothing = NoDatum
173206
getMaybeDatumHash (Just hsh) = DatumHash hsh
174207

208+
fromMultiAssetMap ::
209+
Map (PolicyID StandardCrypto) (Map AssetName Integer) ->
210+
[TxOutMultiAsset]
211+
fromMultiAssetMap = concat . toListBy foldAssets
212+
where
213+
foldAssets :: PolicyID StandardCrypto -> Map AssetName Integer -> [TxOutMultiAsset]
214+
foldAssets policy = toListBy (TxOutMultiAsset policy)
215+
216+
toListBy :: (k -> a -> b) -> Map k a -> [b]
217+
toListBy f = Map.foldrWithKey (\k a xs -> f k a : xs) []
218+
175219
sumTxOutCoin :: [TxOut] -> Coin
176220
sumTxOutCoin = Coin . sum . map (unCoin . txOutAdaValue)
177221

cardano-db-sync/src/Cardano/DbSync/Era/Shelley/Genesis.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ insertTxOuts syncEnv trce blkId (TxIn txInId _, txOut) = do
264264
, C.txOutStakeAddressId = Nothing -- No stake addresses in Shelley Genesis
265265
, C.txOutTxId = txId
266266
, C.txOutValue = Generic.coinToDbLovelace (txOut ^. Core.valueTxOutL)
267+
, C.txOutMaTxOut = Nothing
267268
, C.txOutConsumedByTxId = Nothing
268269
}
269270
DB.TxOutVariantAddress -> do
@@ -284,6 +285,7 @@ insertTxOuts syncEnv trce blkId (TxIn txInId _, txOut) = do
284285
, V.txOutInlineDatumId = Nothing
285286
, V.txOutReferenceScriptId = Nothing
286287
, V.txOutTxId = txId
288+
, V.txOutMaTxOut = Nothing
287289
, V.txOutValue = Generic.coinToDbLovelace (txOut ^. Core.valueTxOutL)
288290
, V.txOutStakeAddressId = Nothing -- No stake addresses in Shelley Genesis
289291
}

cardano-db-sync/src/Cardano/DbSync/Era/Universal/Insert/Tx.hs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import Cardano.DbSync.Cache (queryTxIdWithCache, tryUpdateCacheTx)
2424
import Cardano.DbSync.Cache.Types (CacheStatus (..))
2525
import qualified Cardano.DbSync.Era.Shelley.Generic as Generic
2626
import Cardano.DbSync.Era.Shelley.Generic.Metadata (TxMetadataValue (..), metadataValueToJsonNoSchema)
27-
import Cardano.DbSync.Era.Shelley.Generic.Tx.Types (TxIn (..))
27+
import Cardano.DbSync.Era.Shelley.Generic.Tx.Types (TxIn (..), fromMultiAssetMap)
2828
import Cardano.DbSync.Era.Universal.Insert.Certificate (insertCertificate)
2929
import Cardano.DbSync.Era.Universal.Insert.GovAction (
3030
insertGovActionProposal,
@@ -240,6 +240,7 @@ insertTxOut tracer cache iopts (txId, txHash) (Generic.TxOut index addr value ma
240240
, C.txOutReferenceScriptId = mScriptId
241241
, C.txOutStakeAddressId = mSaId
242242
, C.txOutTxId = txId
243+
, C.txOutMaTxOut = Just multiAssetsJson
243244
, C.txOutValue = Generic.coinToDbLovelace value
244245
}
245246
DB.TxOutVariantAddress -> do
@@ -261,7 +262,9 @@ insertTxOut tracer cache iopts (txId, txHash) (Generic.TxOut index addr value ma
261262
case ioTxOutTableType iopts of
262263
DB.TxOutCore -> ExtendedTxOut txHash txOut
263264
DB.TxOutVariantAddress -> ExtendedTxOut txHash txOut
264-
!maTxOuts <- whenFalseMempty (ioMultiAssets iopts) $ insertMaTxOuts tracer cache maMap
265+
!maTxOuts <-
266+
whenFalseMempty (ioMultiAssets iopts) $
267+
insertMaTxOuts tracer cache maMap
265268
pure (eutxo, maTxOuts)
266269
where
267270
hasScript :: Bool
@@ -270,6 +273,10 @@ insertTxOut tracer cache iopts (txId, txHash) (Generic.TxOut index addr value ma
270273
addrText :: Text
271274
addrText = Generic.renderAddress addr
272275

276+
multiAssetsJson :: Text
277+
multiAssetsJson =
278+
decodeUtf8 . LBS.toStrict . Aeson.encode . fromMultiAssetMap $ maMap
279+
273280
mkTxOutVariant :: Maybe DB.StakeAddressId -> V.AddressId -> Maybe DB.DatumId -> Maybe DB.ScriptId -> V.TxOut
274281
mkTxOutVariant mSaId addrId mDatumId mScriptId =
275282
V.TxOut
@@ -281,6 +288,7 @@ insertTxOut tracer cache iopts (txId, txHash) (Generic.TxOut index addr value ma
281288
, V.txOutReferenceScriptId = mScriptId
282289
, V.txOutTxId = txId
283290
, V.txOutValue = Generic.coinToDbLovelace value
291+
, V.txOutMaTxOut = Just multiAssetsJson
284292
, V.txOutStakeAddressId = mSaId
285293
}
286294

cardano-db/src/Cardano/Db/Schema/Core/TxOut.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ share
4949
stakeAddressId StakeAddressId Maybe noreference
5050
txId TxId noreference
5151
value DbLovelace sqltype=lovelace
52+
maTxOut Text Maybe sqltype=jsonb
5253
UniqueTxout txId index -- The (tx_id, index) pair must be unique.
5354

5455
----------------------------------------------

cardano-db/src/Cardano/Db/Schema/Variant/TxOut.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ share
4747
stakeAddressId StakeAddressId Maybe noreference
4848
txId TxId noreference
4949
value DbLovelace sqltype=lovelace
50+
maTxOut Text Maybe sqltype=jsonb
5051
UniqueTxout txId index -- The (tx_id, index) pair must be unique.
5152

5253
CollateralTxOut

schema/migration-2-0045-20241203.sql

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
-- Persistent generated migration.
2+
3+
CREATE FUNCTION migrate() RETURNS void AS $$
4+
DECLARE
5+
next_version int ;
6+
BEGIN
7+
SELECT stage_two + 1 INTO next_version FROM schema_version ;
8+
IF next_version = 45 THEN
9+
EXECUTE 'ALTER TABLE "reward" ADD COLUMN "id" INT8 NOT NULL' ;
10+
EXECUTE 'ALTER TABLE "reward_rest" ADD COLUMN "id" INT8 NOT NULL' ;
11+
EXECUTE 'ALTER TABLE "tx_out" ADD COLUMN "ma_tx_out" jsonb NULL' ;
12+
-- Hand written SQL statements can be added here.
13+
UPDATE schema_version SET stage_two = next_version ;
14+
RAISE NOTICE 'DB has been migrated to stage_two version %', next_version ;
15+
END IF ;
16+
END ;
17+
$$ LANGUAGE plpgsql ;
18+
19+
SELECT migrate() ;
20+
21+
DROP FUNCTION migrate() ;

0 commit comments

Comments
 (0)