-
Notifications
You must be signed in to change notification settings - Fork 71
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: Add CIP68 Deno example (#562)
- Loading branch information
Showing
13 changed files
with
516 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
*.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
# CIP68 Parser Example | ||
|
||
This example shows how to leverage the Deno filter stage to apply custom parsing logic and extract CIP68 reference NFT data from transaction without the need to change Oura's internal processing pipeline. | ||
|
||
## Configuration | ||
|
||
The relevant section of the daemon.toml is the following: | ||
|
||
```toml | ||
[[filters]] | ||
type = "Deno" | ||
main_module = "./parser.js" | ||
``` | ||
|
||
The above configuration fragment instructs _Oura_ to introduce a _Deno_ filter that uses the logic specified in the file `parser.js`, which holds your custom filter logic. | ||
|
||
The following section explains how to create a .js file compatible with what the Deno filter is expecting. | ||
|
||
## Custom Deno Filter | ||
|
||
To create the custom logic for your Deno-base filter, you need to start by creating a _Typescript_ and implementing a `mapEvent` function: | ||
|
||
```ts | ||
export function mapEvent(record: oura.Event) { | ||
// your custom logic goes here | ||
} | ||
``` | ||
|
||
The above function will be called for each record ths goes through _Oura_'s pipeline. Depending on your configuration, records could represent blocks, transactions or other payloads generated by previous filter stages. | ||
|
||
## CIP68 | ||
|
||
The goal for this particular example is to extract data from transactions that corresponds to reference NFT as defined by [CIP68](https://cips.cardano.org/cips/cip68). | ||
|
||
By inspecting the outputs and Plutus datums from the transactions, we can parse relevant information and generate custom JSON objects such as this one: | ||
|
||
```json | ||
{ | ||
"label": "000643b042756438363031", | ||
"policy": "4523c5e21d409b81c95b45b0aea275b8ea1406e6cafea5583b9f8a5f", | ||
"metadata": { | ||
"name": "SpaceBud #8601", | ||
"traits": "", | ||
"type": "Shark", | ||
"image": "ipfs://bafkreidrqwxpxhyc5bo364fzzwv7nhnjel6y6zkywriw33jopb2p4tba5u", | ||
"sha256": "7185aefb9f02e85dbf70b9cdabf69da922fd8f6558b4516ded2e7874fe4c20ed" | ||
}, | ||
"version": 1, | ||
"txHash": "720dd358d2b28531e181f93eed0e0d24db364232ddaccf6655abf92790a062d5" | ||
} | ||
``` | ||
|
||
You can check the actual code for the parser in the file `parser.ts`. Without going much into detail, the relevant part of the parser is a function called `extractRefNFT`: | ||
|
||
```ts | ||
function extractNFTRef( | ||
output: oura.TxOutputRecord, | ||
allDatums?: oura.PlutusDatumRecord[] | null | ||
): Partial<RefNFT> | null { | ||
const asset = output.assets?.find((a) => a.asset.startsWith("000")); | ||
|
||
if (!asset) return null; | ||
|
||
const datum = | ||
output.inline_datum || | ||
allDatums?.find((d) => d.datum_hash == output.datum_hash); | ||
|
||
if (!datum) return null; | ||
|
||
return { | ||
label: asset.asset, | ||
policy: asset.policy, | ||
...parseDatum(datum), | ||
}; | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
[source] | ||
type = "N2N" | ||
peers = ["relays-new.cardano-mainnet.iohk.io:3001"] | ||
|
||
[intersect] | ||
type = "Point" | ||
value = [ | ||
87938927, | ||
"7d6f25ff981bdc92f6b61c04d7f9d0b7236783da9c66b2d0ba5dc6953b68b34f", | ||
] | ||
|
||
[[filters]] | ||
type = "LegacyV1" | ||
include_transaction_details = true | ||
|
||
[[filters]] | ||
type = "Deno" | ||
main_module = "./parser.js" | ||
|
||
[sink] | ||
type = "Noop" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,254 @@ | ||
export type Era = | ||
| "Undefined" | ||
| "Unknown" | ||
| "Byron" | ||
| "Shelley" | ||
| "Allegra" | ||
| "Mary" | ||
| "Alonzo" | ||
| "Babbage"; | ||
|
||
export type GenericJson = Record<string, unknown>; | ||
|
||
export type MetadatumRendition = { | ||
map_json?: GenericJson; | ||
array_json?: GenericJson; | ||
int_scalar?: string; | ||
text_scalar?: string; | ||
bytes_hex?: string; | ||
}; | ||
|
||
export type MetadataRecord = { | ||
label: string; | ||
content: MetadatumRendition; | ||
}; | ||
|
||
export type CIP25AssetRecord = { | ||
version: string; | ||
policy: string; | ||
asset: string; | ||
name: string | null; | ||
image: string | null; | ||
media_type: string | null; | ||
description: string | null; | ||
raw_json: GenericJson; | ||
}; | ||
|
||
export type CIP15AssetRecord = { | ||
voting_key: string; | ||
stake_pub: string; | ||
reward_address: string; | ||
nonce: number; | ||
raw_json: GenericJson; | ||
}; | ||
|
||
export type TxInputRecord = { | ||
tx_id: string; | ||
index: number; | ||
}; | ||
|
||
export type OutputAssetRecord = { | ||
policy: string; | ||
asset: string; | ||
asset_ascii: string | null; | ||
amount: number; | ||
}; | ||
|
||
export type TxOutputRecord = { | ||
address: string; | ||
amount: number; | ||
assets: OutputAssetRecord[] | null; | ||
datum_hash: string | null; | ||
inline_datum: PlutusDatumRecord | null; | ||
}; | ||
|
||
export type MintRecord = { | ||
policy: string; | ||
asset: string; | ||
quantity: number; | ||
}; | ||
|
||
export type WithdrawalRecord = { | ||
reward_account: string; | ||
coin: number; | ||
}; | ||
|
||
export type TransactionRecord = { | ||
hash: string; | ||
fee: number; | ||
ttl: number | null; | ||
validity_interval_start: number | null; | ||
network_id: number | null; | ||
input_count: number; | ||
collateral_input_count: number; | ||
has_collateral_output: boolean; | ||
output_count: number; | ||
mint_count: number; | ||
total_output: number; | ||
|
||
// include_details | ||
metadata: MetadataRecord[] | null; | ||
inputs: TxInputRecord[] | null; | ||
outputs: TxOutputRecord[] | null; | ||
collateral_inputs: TxInputRecord[] | null; | ||
collateral_output: TxOutputRecord | null; | ||
mint: MintRecord[] | null; | ||
vkey_witnesses: VKeyWitnessRecord[] | null; | ||
native_witnesses: NativeWitnessRecord[] | null; | ||
plutus_witnesses: PlutusWitnessRecord[] | null; | ||
plutus_redeemers: PlutusRedeemerRecord[] | null; | ||
plutus_data: PlutusDatumRecord[] | null; | ||
withdrawals: WithdrawalRecord[] | null; | ||
size: number; | ||
}; | ||
|
||
export type EventContext = { | ||
block_hash: string | null; | ||
block_number: number | null; | ||
slot: number | null; | ||
timestamp: number | null; | ||
tx_idx: number | null; | ||
tx_hash: string | null; | ||
input_idx: number | null; | ||
output_idx: number | null; | ||
output_address: string | null; | ||
certificate_idx: number | null; | ||
}; | ||
|
||
export type StakeCredential = { | ||
addr_keyhash?: string; | ||
scripthash?: string; | ||
}; | ||
|
||
export type VKeyWitnessRecord = { | ||
vkey_hex: string; | ||
signature_hex: string; | ||
}; | ||
|
||
export type NativeWitnessRecord = { | ||
policy_id: string; | ||
script_json: GenericJson; | ||
}; | ||
|
||
export type PlutusWitnessRecord = { | ||
script_hash: string; | ||
script_hex: string; | ||
}; | ||
|
||
export type PlutusRedeemerRecord = { | ||
purpose: string; | ||
ex_units_mem: number; | ||
ex_units_steps: number; | ||
input_idx: number; | ||
plutus_data: GenericJson; | ||
}; | ||
|
||
export type PlutusDatumRecord = { | ||
datum_hash: string; | ||
plutus_data: GenericJson; | ||
}; | ||
|
||
export type BlockRecord = { | ||
era: Era; | ||
epoch: number | null; | ||
epoch_slot: number | null; | ||
body_size: number; | ||
issuer_vkey: string; | ||
vrf_vkey: string; | ||
tx_count: number; | ||
slot: number; | ||
hash: string; | ||
number: number; | ||
previous_hash: string; | ||
cbor_hex: string | null; | ||
transactions: TransactionRecord[] | null; | ||
}; | ||
|
||
export type CollateralRecord = { | ||
tx_id: string; | ||
index: number; | ||
}; | ||
|
||
export type PoolRegistrationRecord = { | ||
operator: string; | ||
vrf_keyhash: string; | ||
pledge: number; | ||
cost: number; | ||
margin: number; | ||
reward_account: string; | ||
pool_owners: string[]; | ||
relays: string[]; | ||
pool_metadata: string | null; | ||
pool_metadata_hash: string | null; | ||
}; | ||
|
||
export type RollBackRecord = { | ||
block_slot: number; | ||
block_hash: string; | ||
}; | ||
|
||
export type MoveInstantaneousRewardsCertRecord = { | ||
from_reserves: boolean; | ||
from_treasury: boolean; | ||
to_stake_credentials: Array<[StakeCredential, number]> | null; | ||
to_other_pot: number | null; | ||
}; | ||
|
||
export type NativeScriptRecord = { | ||
policy_id: string; | ||
script: GenericJson; | ||
}; | ||
|
||
export type PlutusScriptRecord = { | ||
hash: string; | ||
data: string; | ||
}; | ||
|
||
export type StakeRegistrationRecord = { credential: StakeCredential }; | ||
|
||
export type StakeDeregistrationRecord = { credential: StakeCredential }; | ||
|
||
export type StakeDelegation = { | ||
credential: StakeCredential; | ||
pool_hash: string; | ||
}; | ||
|
||
export type PoolRetirementRecord = { | ||
pool: string; | ||
epoch: number; | ||
}; | ||
|
||
export type GenesisKeyDelegationRecord = {}; | ||
|
||
export type Event = { | ||
context: EventContext; | ||
fingerprint?: string; | ||
|
||
block?: BlockRecord; | ||
block_end?: BlockRecord; | ||
transaction?: TransactionRecord; | ||
transaction_end?: TransactionRecord; | ||
tx_input?: TxInputRecord; | ||
tx_output?: TxOutputRecord; | ||
output_asset?: OutputAssetRecord; | ||
metadata?: MetadataRecord; | ||
v_key_witness?: VKeyWitnessRecord; | ||
native_witness?: NativeWitnessRecord; | ||
plutus_witness?: PlutusWitnessRecord; | ||
plutus_redeemer?: PlutusRedeemerRecord; | ||
plutus_datum?: PlutusDatumRecord; | ||
cip25_asset?: CIP25AssetRecord; | ||
cip15_asset?: CIP15AssetRecord; | ||
mint?: MintRecord; | ||
collateral?: CollateralRecord; | ||
native_script?: NativeScriptRecord; | ||
plutus_script?: PlutusScriptRecord; | ||
stake_registration?: StakeRegistrationRecord; | ||
stake_deregistration?: StakeDeregistrationRecord; | ||
stake_delegation?: StakeDelegation; | ||
pool_registration?: PoolRegistrationRecord; | ||
pool_retirement?: PoolRetirementRecord; | ||
genesis_key_delegation?: GenesisKeyDelegationRecord; | ||
move_instantaneous_rewards_cert?: MoveInstantaneousRewardsCertRecord; | ||
roll_back?: RollBackRecord; | ||
}; |
Oops, something went wrong.