├── .gitignore ├── docs └── cta-v1-pink.png ├── .vscode └── settings.json ├── .editorconfig ├── tsconfig.json ├── src ├── context.ts ├── local-state-query.ts ├── local-mempool-monitor.ts └── local-chain-sync.ts ├── package.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /docs/cta-v1-pink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CardanoSolutions/ogmios-ts-client-starter-kit/HEAD/docs/cta-v1-pink.png -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workbench.startupEditor": "readme", 3 | "workbench.editorAssociations": { 4 | "README.md": "vscode.markdown.preview.editor", 5 | } 6 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.ts] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2017", 5 | "esModuleInterop": true, 6 | "rootDir": "./src", 7 | "outDir": "./dist" 8 | }, 9 | "exclude": ["node_modules"] 10 | } -------------------------------------------------------------------------------- /src/context.ts: -------------------------------------------------------------------------------- 1 | import { createInteractionContext } from '@cardano-ogmios/client' 2 | 3 | export const createContext = () => createInteractionContext( 4 | err => console.error(err), 5 | () => console.log("Connection closed."), 6 | { connection: { host: process.env.OGMIOS_HOST, port: parseInt(process.env.OGMIOS_PORT, 10) } } 7 | ); 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ogmios-client-starter-kit", 3 | "version": "1.2.0", 4 | "description": "An example start kit for Ogmios with the TypeScript client", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "tsc", 8 | "local-chain-sync": "npm run build && node dist/local-chain-sync.js", 9 | "local-state-query": "npm run build && node dist/local-state-query.js", 10 | "local-mempool-monitor": "npm run build && node dist/local-mempool-monitor.js" 11 | }, 12 | "author": "Scarmuega , KtorZ ", 13 | "license": "MPL-2.0", 14 | "devDependencies": { 15 | "@types/ws": "^8.5.3", 16 | "typescript": "^4.8.3" 17 | }, 18 | "dependencies": { 19 | "@cardano-ogmios/client": "^6.0.0", 20 | "@types/node": "^18.7.15", 21 | "ws": "^8.14.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/local-state-query.ts: -------------------------------------------------------------------------------- 1 | import { createLedgerStateQueryClient } from '@cardano-ogmios/client'; 2 | import { createContext } from './context'; 3 | 4 | function handleBigInt(_, v: unknown): any { 5 | return typeof v === 'bigint' ? Number(v) : v 6 | } 7 | 8 | export async function runExample() { 9 | const context = await createContext(); 10 | const client = await createLedgerStateQueryClient(context) 11 | 12 | const height = await client.networkBlockHeight(); 13 | console.log(`=== Network height\n${height}\n`); 14 | 15 | const tip = await client.networkTip(); 16 | console.log(`=== Network tip\n${JSON.stringify(tip, null, 2)}\n`); 17 | 18 | const params = await client.protocolParameters(); 19 | delete params.plutusCostModels; // Lots of noise 20 | console.log(`=== Protocol parameters\n${JSON.stringify(params, handleBigInt, 2)}`); 21 | 22 | client.shutdown(); 23 | } 24 | 25 | runExample() 26 | -------------------------------------------------------------------------------- /src/local-mempool-monitor.ts: -------------------------------------------------------------------------------- 1 | import { 2 | createMempoolMonitoringClient, 3 | MempoolMonitoring, 4 | } from '@cardano-ogmios/client'; 5 | import { 6 | TransactionId 7 | } from '@cardano-ogmios/schema'; 8 | import { 9 | createContext 10 | } from './context'; 11 | 12 | async function flushMempool( 13 | client: MempoolMonitoring.MempoolMonitoringClient 14 | ): Promise { 15 | let transactions = []; 16 | 17 | for(;;){ 18 | const transactionId = await client.nextTransaction(); 19 | if (transactionId !== null) { 20 | transactions.push(transactionId); 21 | } else { 22 | break; 23 | } 24 | } 25 | 26 | return transactions; 27 | } 28 | 29 | export async function runExample() { 30 | const context = await createContext(); 31 | const client = await createMempoolMonitoringClient(context); 32 | 33 | while (true) { 34 | await client.acquireMempool(); 35 | const transactions = await flushMempool(client); 36 | const capacity = await client.sizeOfMempool(); 37 | console.log(`Local mempool: ${JSON.stringify({ ...capacity, transactions }, null, 2)}`); 38 | console.log(`Awaiting for changes in the mempool...`); 39 | } 40 | 41 | client.shutdown(); 42 | } 43 | 44 | runExample(); 45 | -------------------------------------------------------------------------------- /src/local-chain-sync.ts: -------------------------------------------------------------------------------- 1 | import { 2 | createChainSynchronizationClient 3 | } from '@cardano-ogmios/client' 4 | import { 5 | Block, 6 | BlockPraos, 7 | DigestBlake2B256, 8 | Point, 9 | Slot, 10 | } from '@cardano-ogmios/schema'; 11 | import { 12 | createContext 13 | } from './context'; 14 | 15 | 16 | /* A dummy database implementation. */ 17 | class Database { 18 | blocks: Block[]; 19 | 20 | constructor() { 21 | this.blocks = []; 22 | } 23 | 24 | rollForward(block : Block) { 25 | this.blocks.push(block); 26 | } 27 | 28 | rollBackward(point : Point) { 29 | this.blocks.filter(block => (block as BlockPraos).slot <= point.slot); 30 | } 31 | 32 | getBlock(point : Point) { 33 | return this.blocks.filter(block => block.id == point.id); 34 | } 35 | } 36 | 37 | // Avoids error when serializing BigInt 38 | const replacer = (_key: any, value: any) => typeof value === 'bigint' ? value.toString() : value; 39 | 40 | const rollForward = (db : Database) => async ({ block }: { block: Block }, requestNextBlock: () => void) => { 41 | console.log(`Roll forward: ${JSON.stringify(block, replacer)}`); 42 | db.rollForward(block); 43 | requestNextBlock(); 44 | } 45 | 46 | const rollBackward = (db : Database) => async ({ point }: any, requestNextBlock: () => void) => { 47 | console.log(`Roll backward: ${JSON.stringify(point)}`); 48 | db.rollBackward(point); 49 | requestNextBlock(); 50 | } 51 | 52 | export async function runExample() { 53 | const context = await createContext(); 54 | const db = new Database(); 55 | const client = await createChainSynchronizationClient(context, { 56 | rollForward: rollForward(db), 57 | rollBackward: rollBackward(db), 58 | }); 59 | await client.resume(); 60 | } 61 | 62 | runExample() 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ogmios Client Starter Kit 2 | 3 | This repo provides a NodeJS package with several examples of how to leverage Ogmios typescript client to: 4 | 5 | ✓ Execute ledger state and network queries;
6 | ✓ Synchronize blocks from the chain;
7 | ✓ Monitor a local mempool;
8 | ✓ Submit or evaluate transactions
9 | 10 | ## Dev Environment 11 | 12 | ### Option #1: Manual Setup 13 | 14 | For running this starter kit you'll need access to an Ogmios instance connected to a fully synced instance of a Cardano Node. You can read the setup instructions on the documentation for each corresponding component 15 | 16 | ### Option #2: Demeter.run 17 | 18 | If you don't want to install the required components yourself, you can use [Demeter.run](https://demeter.run) platform to create a cloud environment with access to common Cardano infrastrcuture. The following command will open this repo in a private, web-based VSCode IDE with access to a shared Cardano Node and Ogmios. 19 | 20 | [![Run in Cardano Workspace](https://demeter.run/code/badge.svg)](https://demeter.run/code/?repository=https://github.com/CardanoSolutions/ogmios-client-starter-kit.git&template=typescript) 21 | 22 | ## Getting started 23 | 24 | > **Note** 25 | > The following instructions assumes that you're using a Cardano Workspace. 26 | 27 | Once you've finished with the Cardano Workspace creation process, you should be able to access this codebase from a VSCode IDE instance. Open this README file using the Markdown Preview command to continue this guide from inside the workspace. 28 | 29 | Since this is a Node.js package, the next step is to install the dependencies. This can be done by opening the embedded terminal within the VSCode IDE. 30 | 31 | > **Note** 32 | > There's no need to install NodeJS or NPM, these tools are already available as part of your workspace. 33 | 34 | From within the terminal, run the following yarn command to install the dependencies: 35 | 36 | ```sh 37 | yarn 38 | ``` 39 | 40 | When yarn finishes, you should be able to execute the examples. 41 | 42 | ### Run the Local-State-Query example 43 | 44 | This example shows how to connect to Ogmios using the Local-State-Query mini-protocol, which allows us to execute queries about the state of the node using request / response semantics. 45 | 46 | The code for this example lives in `src/local-state-query.ts`. To start the example, you can run the script called `local-state-query` defined in the `package.json` file. Open the embedded VSCode terminal and execute the following command: 47 | 48 | ```sh 49 | yarn local-state-query 50 | ``` 51 | 52 | ### Run the Local-Chain-Sync example 53 | 54 | This example shows how to connect to Ogmios using the Local-Chain-Sync mini-protocol, which allows us to synchronize the state of the chain by "pulling" block data. 55 | 56 | The code for this example lives in `src/local-chain-sync.ts`. To start the example, you can run the script called `local-chain-sync` defined in the `package.json` file. Open the embedded VSCode terminal and execute the following command: 57 | 58 | ```sh 59 | yarn local-chain-sync 60 | ``` 61 | 62 | ### Run the Local-Mempool-Monitor example 63 | 64 | This example shows a basic scenario of fetching transactions from your node mempool. If your node is running as a simple relay, then the transactions list is likely empty. However, you can try visualizing transactions in the mempool by submitting some while the example scenario is running. 65 | 66 | Note that this example never exits and will await for changes in the mempool to happen. 67 | 68 | The code for this example lives in `src/local-mempool-monitor.ts`. To start the example, you can run the script called `local-mempool-monitor` defined in the `package.json` file. Open the embedded VSCode terminal and execute the following command: 69 | 70 | ```sh 71 | yarn local-mempool-monitor 72 | ``` 73 | 74 | --- 75 | 76 | > **Warning** 77 | > The local-chain-sync example does not terminate, it'll start synchronizing blocks from the network tip until your stop it (`CTRL-C`). You'll also notice that it always starts with a _Roll backward_ instruction, from where it'll continue syncing. 78 | 79 | ## FAQ 80 | 81 | ### How do I connect to the Ogmios instance? 82 | 83 | Ogmios works as a lightweight bridge between the Cardano Node and HTTP web-socket clients. There are many client libraries available but we'll be using only the Typescript client for this starter-kit. 84 | 85 | To initialize the client library, the host and port where the **Ogmios instance is listening needs to be specified. 86 | 87 | > **Note** 88 | > When running inside a _Cardano Workspace_, these values are already available as environmental variables: `OGMIOS_HOST` and `OGMIOS_PORT`. 89 | 90 | The following snippet shows an exmample of how to setup an "interaction context" that will hold the connection between your client and the Ogmios instance. 91 | 92 | ```ts 93 | import { createInteractionContext } from '@cardano-ogmios/client' 94 | 95 | const context = createInteractionContext( 96 | err => console.error(err), 97 | () => console.log("Connection closed."), 98 | { connection: { host: process.env.OGMIOS_HOST, port: parseInt(process.env.OGMIOS_PORT!) } } 99 | ); 100 | ``` 101 | 102 | ### Where can I get more info about Ogmios? 103 | 104 | Ogmios is developed by [Cardano Solutions](https://github.com/cardanosolutions). The codebase lives in the [CardanoSolutions/Ogmios](https://github.com/cardanosolutions/ogmios) Github repository. Technical documentation and API reference can be found at [ogmios.dev](https://ogmios.dev/). 105 | 106 | ## DIY Ideas 107 | 108 | Here are some ideas on how to continue the development of this starter kit as a way to understand the rest of Ogmios features. These tasks can be acomplished by reading the Ogmios [typescript client documentation](https://ogmios.dev/typescript/api/modules/_cardano_ogmios_client.html) and some extrapolation from the existing examples: 109 | 110 | - [ ] Query a particular UTxO by output reference. 111 | 112 | - [ ] Submit a transaction using the _Transaction Submission_ mini-protocol. 113 | 114 | - [ ] Check the state of the mempool using the _Mempool Monitoring_ mini-protocol. 115 | --------------------------------------------------------------------------------