Skip to content

Commit

Permalink
Merge pull request #34 from PaimaStudios/update-cardano-primitives
Browse files Browse the repository at this point in the history
Update Cardano primitive docs
  • Loading branch information
SebastienGllmt authored Mar 26, 2024
2 parents 942f887 + 7e808b6 commit 9c6bd56
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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).
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -40,14 +44,36 @@ const cardanoMint: ParserRecord<CardanoMint> = {
},
};
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.
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
Original file line number Diff line number Diff line change
@@ -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<ICdeCardanoGetProjectedNftResult[]>;
```

0 comments on commit 9c6bd56

Please sign in to comment.