diff --git a/docs/home/300-react-to-events/2-primitive-catalogue/20-cardano/20-delayed-state.md b/docs/home/300-react-to-events/2-primitive-catalogue/20-cardano/20-delayed-state.md index 3fbb1f81..7294e01d 100644 --- a/docs/home/300-react-to-events/2-primitive-catalogue/20-cardano/20-delayed-state.md +++ b/docs/home/300-react-to-events/2-primitive-catalogue/20-cardano/20-delayed-state.md @@ -6,6 +6,8 @@ However, not all use-cases care about having the data entirely up-to-date. For e This delay is also generically unavoidable with chains that don't have instant finality like Cardano as we generally want our app to update only with changes that have been finalized (which takes time). +If you're looking to track when these assets were minted/burned, use the [mint-burn](./40-cardano-mint-burn.md) primitive. + ## Delayed asset {#delayed-asset} ### Example diff --git a/docs/home/300-react-to-events/2-primitive-catalogue/20-cardano/30-cardano-transfer.md b/docs/home/300-react-to-events/2-primitive-catalogue/20-cardano/30-cardano-transfer.md index 0de4c67f..7c5dd3fa 100644 --- a/docs/home/300-react-to-events/2-primitive-catalogue/20-cardano/30-cardano-transfer.md +++ b/docs/home/300-react-to-events/2-primitive-catalogue/20-cardano/30-cardano-transfer.md @@ -4,6 +4,8 @@ Keeps track of the entire (between the indexed slots) transaction history of a payment credential or particular address. +This primitive only gets triggered a single time per transaction (even if the transaction contains multiple outputs to the specified address) + ### Example ```yaml @@ -62,7 +64,19 @@ interface CardanoTransfer { - The metadata field is in its binary form, but hex encoded. - The entries in `inputCredentials` are also hex encoded. Each one is the binary -representation of the payment key (64 characters or 32 bytes). +representation of the payment key (64 characters or 32 bytes). This can give a hint on who made the transaction (see [below](#who-paid) for more on this). - `outputs` preserves the same order as in the binary transaction. The `asset` will be `null` when the amount is in lovelace. +### Detecting who made the payment {#who-paid} + +Trying to detect who actually made the transaction is difficult because transactions in Cardano can have multiple inputs and multiple outputs. + +Example of edge-cases: +1. Multiple input addresses that don't belong to the user (ex: multiple exchanges addresses) +2. Script credentials (instead of payment credentials) +3. Funds coming from other mechanisms like reward withdrawal or pool deposit refunds + +Therefore, although we provide access to the list of `inputCredentials`, if possible it is better to define a specific metadata format for your application that includes which address the payment should be credited to. The `metadata` for the transaction is given as part of the primitive. + +Additionally, in cases where there are multiple outputs in the same transaction that trigger this primitive, we only trigger this primitive once. It is up to the app if it wants to aggregate multiple output values as a single payment, or keep them separated (possibly with a metadata hint about which address gets credited how much). diff --git a/docs/home/300-react-to-events/2-primitive-catalogue/20-cardano/40-cardano-mint-burn.md b/docs/home/300-react-to-events/2-primitive-catalogue/20-cardano/40-cardano-mint-burn.md index b568c697..186f47bd 100644 --- a/docs/home/300-react-to-events/2-primitive-catalogue/20-cardano/40-cardano-mint-burn.md +++ b/docs/home/300-react-to-events/2-primitive-catalogue/20-cardano/40-cardano-mint-burn.md @@ -1,5 +1,9 @@ # Cardano Mint and Burn {#mint-burn} +Tracks all the instances of a mint or burn of set of policy IDs. + +If you're looking to track these assets after they've been minted, use the [delayed state](./20-delayed-state.md) primitive. + ### Example ```yaml @@ -40,14 +44,36 @@ const cardanoMint: ParserRecord = { }, }; +interface AssetAmount { + policyId: string; + assetName: string; + amount: string; +} export interface CardanoMint { txId: string; metadata: string | null; - assets: { asset: { policyId: string; assetName: string }; amount: string }; + assets: { [policyId: string]: { [assetName: string]: string } }; + inputAddresses: { [address: string]: AssetAmount[] } + outputAddresses: { [address: string]: AssetAmount[] } } ``` - The `metadata` field is hex encoded (if any), and it's the metadata in binary form. - The `assets` field has the minted or burned assets. The difference between a -mint and a burn is in the sign of `amount` when interpreted as a number. \ No newline at end of file +mint and a burn is in the sign of `amount` when interpreted as a number. +- The `inputAddresses` represents addresses who at least partially burned the tracked tokens +- The `outputAddresses` represents addresses who at least partially minted the tracked tokens + +### Detecting who minted and who burned + +Some key facts about Cardano transactions to help understand how to parse this information: +- Cardano transactions can contain multiple mints & burns of different tokens in the same transaction +- Different addresses can mint/burn tokens in the same transactions (txs have multiple inputs & outputs) +- The same address can mint/burn multiple times in the same transaction (different inputs or different outputs) +- All mints & burns share the same `metadata` field + +A consequence of this is that not all the token supply found in the input may have been burned. In other words, the following transaction is possible: +1. `inputAddresses` contains 50 token X +2. `assets` contains -30 token X +3. `outputAddresses` contains 20 token X diff --git a/docs/home/300-react-to-events/2-primitive-catalogue/20-cardano/50-projected-nft.md b/docs/home/300-react-to-events/2-primitive-catalogue/20-cardano/50-projected-nft.md new file mode 100644 index 00000000..b9df4b0d --- /dev/null +++ b/docs/home/300-react-to-events/2-primitive-catalogue/20-cardano/50-projected-nft.md @@ -0,0 +1,67 @@ +# Cardano Projected NFT + +Different blockchains may have different block times & finality, so trying to guarantee the state of blockchain A from blockchain B often requires timelock systems like [projected data](../../../700-multichain-support/1-nfts/2-projected-nfts/1-basics.mdx). + +This primitive implements the Projected NFT system and, given Cardano NFTs are treated the same as any other asset in a UTXO, is seamlessly extended to be a general projected asset system (it is not limited to NFTs). + +If your use-case does not require a guarantee the data is up-to-date to the second, consider using [the delayed state primitive](./20-delayed-state.md) instead. + +## Projected NFT {#projected-nft} + +### Example + +```yaml +extensions: + - name: "projected-nft" + scheduledPrefix: cpn + type: cardano-projected-nft + startSlot: 22505578 + stopSlot: 32815924 + network: CardanoNetworkConfigEntryName +``` + +### Meaning + +- `startSlot` is required and means that only events after that slot (exclusive) + will be considered. This should be a slot that happened before the first + transaction involving the assets. +- `stopSlot` is optional, and it stops the indexing at that point. + +### Paima Concise format + +The scheduled input for each event is of the following form. + +``` +cardanoTransfer = cpn|ownerAddress|previousTxHash|previousOutputIndex|currentTxHash|currentOutputIndex|policyId|assetName|status +``` + +Where `status` is one of: +- `Lock` +- `Unlocking` +- `Claim` +- `Invalid` + +### Utility functions + +You can get all the projected NFTs for an address with the utility function below + +```ts +export interface ICdeCardanoGetProjectedNftResult { + amount: string; + asset_name: string; + current_tx_hash: string; + current_tx_output_index: number | null; + for_how_long: string | null; + owner_address: string; + plutus_datum: string; + policy_id: string; + previous_tx_hash: string | null; + previous_tx_output_index: number | null; + status: 'Lock' | 'Unlocking' | 'Claim' | 'Invalid'; +} + +export declare function getCardanoAddressProjectedNfts( + readonlyDBConn: Pool, + address: string +): Promise; +```