Skip to content

Commit 7774af5

Browse files
author
kuber-dev
committed
Add examples for burning native tokens, paying to a script, and payment to 100+ addresses
1 parent e4adaa5 commit 7774af5

5 files changed

Lines changed: 366 additions & 11 deletions

File tree

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
---
2+
sidebar_position: 7
3+
sidebar_label: Burning Native Tokens
4+
---
5+
6+
# Burning Native Tokens
7+
8+
This guide demonstrates how to burn native tokens in an open Hydra Head using a CIP-30 wallet and `KuberHydraApiProvider`.
9+
10+
## When to use this flow
11+
12+
Use token burn when you need to reduce total circulating supply for a policy, invalidate temporary in-app assets, or clean up test assets after scenario runs.
13+
14+
## Prerequisites
15+
16+
- Node.js environment
17+
- `libcardano` and `libcardano-wallet` installed
18+
- An active Hydra Head in `Open` state
19+
- A wallet that currently holds the token you want to burn
20+
- The same mint policy used when the token was created
21+
22+
## Example: Burn 1 `Token1`
23+
24+
```typescript
25+
import { KuberHydraApiProvider } from "kuber-client";
26+
import { CardanoKeyAsync } from "libcardano";
27+
import { ShelleyWallet, SimpleCip30Wallet } from "libcardano-wallet";
28+
import { readFileSync } from "fs";
29+
30+
async function runBurnNativeTokensExample() {
31+
const hydra = new KuberHydraApiProvider("http://localhost:8082");
32+
33+
const signingKey = await CardanoKeyAsync.fromCardanoCliJson(
34+
JSON.parse(
35+
readFileSync(
36+
process.env.HOME + "/.cardano/preview/hydra-0/credentials/funds.sk",
37+
"utf-8",
38+
),
39+
),
40+
);
41+
42+
const shelleyWallet = new ShelleyWallet(signingKey);
43+
const wallet = new SimpleCip30Wallet(hydra, hydra, shelleyWallet, 0);
44+
const walletAddress = (await wallet.getChangeAddress()).toBech32();
45+
46+
const headState = await hydra.queryHeadState();
47+
if (headState.state !== "Open") {
48+
throw new Error(`Hydra head is ${headState.state}. Expected Open.`);
49+
}
50+
51+
// Negative amount burns assets under the policy script.
52+
const burnTx = {
53+
mint: [
54+
{
55+
script: {
56+
type: "sig",
57+
keyHash: shelleyWallet.paymentKey.pkh.toString("hex"),
58+
},
59+
amount: {
60+
Token1: -1,
61+
},
62+
},
63+
],
64+
changeAddress: walletAddress,
65+
};
66+
67+
const result = await hydra.buildAndSubmitWithWallet(wallet, burnTx);
68+
console.log("Burn transaction submitted:", result.transaction.toBytes().toString("hex"));
69+
}
70+
71+
runBurnNativeTokensExample().catch((err) => {
72+
console.error("Burn flow failed:", err);
73+
});
74+
```
75+
76+
## Verify the burn
77+
78+
1. Query wallet UTxOs before and after the burn.
79+
2. Confirm token quantity decreased by the expected amount.
80+
3. Confirm no policy mismatch error occurred.
81+
82+
## Common issues
83+
84+
- `ValueNotConservedUTxO`: burn amount is larger than wallet token balance.
85+
- Script witness failure: policy script/key hash does not match minted asset policy.
86+
- Head not open: call this flow only after commit + head open.
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
---
2+
sidebar_position: 8
3+
sidebar_label: Paying to a Script
4+
---
5+
6+
# Paying to a Script
7+
8+
This guide demonstrates how to create a transaction output locked by a script address (pay-to-script) from within an open Hydra Head.
9+
10+
## Why this matters
11+
12+
Pay-to-script is the base workflow for contract-driven interactions: escrow, conditional settlement, and state-machine style protocols.
13+
14+
## Prerequisites
15+
16+
- Node.js environment
17+
- `libcardano` and `libcardano-wallet` installed
18+
- An active Hydra Head in `Open` state
19+
- Script address available for your target validator
20+
- Datum format agreed by your application
21+
22+
## Example: Lock 5 ADA at script address
23+
24+
```typescript
25+
import { KuberHydraApiProvider } from "kuber-client";
26+
import { CardanoKeyAsync } from "libcardano";
27+
import { ShelleyWallet, SimpleCip30Wallet } from "libcardano-wallet";
28+
import { readFileSync } from "fs";
29+
30+
async function runPayToScriptExample() {
31+
const hydra = new KuberHydraApiProvider("http://localhost:8082");
32+
33+
const signingKey = await CardanoKeyAsync.fromCardanoCliJson(
34+
JSON.parse(
35+
readFileSync(
36+
process.env.HOME + "/.cardano/preview/hydra-0/credentials/funds.sk",
37+
"utf-8",
38+
),
39+
),
40+
);
41+
42+
const shelleyWallet = new ShelleyWallet(signingKey);
43+
const wallet = new SimpleCip30Wallet(hydra, hydra, shelleyWallet, 0);
44+
const walletAddress = (await wallet.getChangeAddress()).toBech32();
45+
46+
const headState = await hydra.queryHeadState();
47+
if (headState.state !== "Open") {
48+
throw new Error(`Hydra head is ${headState.state}. Expected Open.`);
49+
}
50+
51+
// Replace this with your real validator address.
52+
const scriptAddress = "addr_test1wq...your_script_address";
53+
54+
const txBuilder = {
55+
outputs: [
56+
{
57+
address: scriptAddress,
58+
value: "5000000",
59+
datum: {
60+
constructor: 0,
61+
fields: [
62+
{ int: 42 },
63+
{ bytes: "68656c6c6f" },
64+
],
65+
},
66+
},
67+
],
68+
changeAddress: walletAddress,
69+
};
70+
71+
const txHash = await hydra.buildAndSubmitWithWallet(wallet, txBuilder);
72+
console.log("Pay-to-script tx submitted:", txHash);
73+
}
74+
75+
runPayToScriptExample().catch((err) => {
76+
console.error("Pay-to-script flow failed:", err);
77+
});
78+
```
79+
80+
## Validate output exists
81+
82+
1. Query Hydra UTxO set and filter by script address.
83+
2. Confirm datum is present in the output.
84+
3. Use your script spending flow in a follow-up transaction.
85+
86+
## Notes
87+
88+
- Datum shape must match validator expectation.
89+
- Keep datum minimal where possible to reduce transaction size.
90+
- If spending from script later, include required redeemer and script witness.
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
---
2+
sidebar_position: 9
3+
sidebar_label: Payment to 100+ Addresses
4+
---
5+
6+
# Payment to 100+ New Addresses (Minimum 2 ADA Each)
7+
8+
This guide demonstrates how to build high-fanout payment transactions in Hydra where each new recipient gets at least 2 ADA.
9+
10+
## Goal
11+
12+
- Pay to more than 100 recipient addresses.
13+
- Enforce at least `2_000_000` lovelace per output.
14+
- Submit in safe chunks to avoid transaction size limits.
15+
16+
## Prerequisites
17+
18+
- Node.js environment
19+
- `libcardano` and `libcardano-wallet` installed
20+
- An active Hydra Head in `Open` state
21+
- Source wallet funded for total transfer + fees
22+
23+
## Example strategy
24+
25+
1. Build a recipient list (100+ addresses).
26+
2. Split into chunks (example: 40 outputs per tx).
27+
3. Submit each chunk sequentially.
28+
29+
```typescript
30+
import { KuberHydraApiProvider } from "kuber-client";
31+
import { CardanoKeyAsync } from "libcardano";
32+
import { ShelleyWallet, SimpleCip30Wallet } from "libcardano-wallet";
33+
import { readFileSync } from "fs";
34+
35+
const MIN_PER_OUTPUT = 2_000_000;
36+
const CHUNK_SIZE = 40;
37+
38+
function chunk<T>(items: T[], size: number): T[][] {
39+
const chunks: T[][] = [];
40+
for (let i = 0; i < items.length; i += size) {
41+
chunks.push(items.slice(i, i + size));
42+
}
43+
return chunks;
44+
}
45+
46+
async function runBulkPaymentExample() {
47+
const hydra = new KuberHydraApiProvider("http://localhost:8082");
48+
49+
const signingKey = await CardanoKeyAsync.fromCardanoCliJson(
50+
JSON.parse(
51+
readFileSync(
52+
process.env.HOME + "/.cardano/preview/hydra-0/credentials/funds.sk",
53+
"utf-8",
54+
),
55+
),
56+
);
57+
58+
const shelleyWallet = new ShelleyWallet(signingKey);
59+
const wallet = new SimpleCip30Wallet(hydra, hydra, shelleyWallet, 0);
60+
const changeAddress = (await wallet.getChangeAddress()).toBech32();
61+
62+
const headState = await hydra.queryHeadState();
63+
if (headState.state !== "Open") {
64+
throw new Error(`Hydra head is ${headState.state}. Expected Open.`);
65+
}
66+
67+
// Replace with real generated/imported recipient addresses.
68+
const recipients = Array.from({ length: 105 }).map(
69+
(_, i) => `addr_test1...recipient_${i}`,
70+
);
71+
72+
const batches = chunk(recipients, CHUNK_SIZE);
73+
74+
for (let batchIndex = 0; batchIndex < batches.length; batchIndex += 1) {
75+
const outputs = batches[batchIndex].map((address) => ({
76+
address,
77+
value: String(MIN_PER_OUTPUT),
78+
}));
79+
80+
const txBuilder = {
81+
outputs,
82+
changeAddress,
83+
};
84+
85+
const txHash = await hydra.buildAndSubmitWithWallet(wallet, txBuilder);
86+
console.log(`Batch ${batchIndex + 1}/${batches.length} submitted:`, txHash);
87+
}
88+
}
89+
90+
runBulkPaymentExample().catch((err) => {
91+
console.error("Bulk payment flow failed:", err);
92+
});
93+
```
94+
95+
## Validation checklist
96+
97+
1. All intended recipient addresses were included.
98+
2. Every output value is at least 2 ADA.
99+
3. All chunks were accepted by the Hydra head.
100+
4. Source wallet balance decreased by expected total.
Lines changed: 87 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,99 @@
1-
# Overview
1+
# Getting Started with Kuber-Hydra
22

3-
Welcome! In order to get started with Hydra with Kuber, you will need to connect to a cardano-node, setup a
4-
hydra cluster and run kuber-server.
3+
Use this page as your launchpad for real Hydra development with Kuber. You will find setup paths, API references, and practical end-to-end examples you can run immediately.
54

5+
## What Kuber-Hydra gives you
66

7-
### What you will run
7+
Kuber-Hydra provides a developer-friendly relay API around Hydra nodes so you can:
8+
9+
- Build and submit in-head transactions with a familiar TxBuilder flow.
10+
- Query head state, UTxOs, and protocol parameters from one place.
11+
- Drive full head lifecycle operations (`initialize`, `commit`, `close`, `fanout`) without wiring low-level Hydra protocol code yourself.
12+
13+
In short: you write app transaction logic, and Kuber-Hydra handles most of the operational integration work.
14+
15+
## What you will run
816

917
- A Cardano node (local devnet or testnet/mainnet)
10-
- 3 Hydra nodes for Alice, Bob, Carol
11-
- 3 Kuber-Hydra server for Alice, Bob, Carol
18+
- 3 Hydra nodes for Alice, Bob, and Carol
19+
- 3 Kuber-Hydra relay servers for Alice, Bob, and Carol
20+
21+
## Recommended prerequisites
22+
23+
Before running examples, make sure you have:
24+
25+
- Node.js 18+
26+
- A package manager (`pnpm`, `yarn`, or `npm`)
27+
- Docker Desktop (required for local devnet flow)
28+
- Wallet/signing key files for participants
29+
- Enough funds for commit/collateral scenarios
30+
31+
If you are just starting, use local devnet first. It is faster, deterministic, and easier to debug.
32+
33+
## Choose your setup path
34+
35+
### Quick start: [Local devnet](./local-devnet.md)
36+
37+
Best for fast iteration and repeatable testing. You can run full head lifecycle and transaction scenarios without waiting for public-network confirmations.
38+
39+
### 🌐 Real network: [Testnet/Mainnet](./testnet_or_mainnet.md)
40+
41+
Best for realistic integration conditions. Use this path when validating wallet behavior, infrastructure setup, and production-like transaction flow.
42+
43+
## First run checklist using Quick Start
44+
See more for API details - [Kuber-Hydra API reference](../kuber-hydra-api-reference.md)
45+
46+
1. Start local cluster and verify relays are reachable.
47+
2. Query `/query/head` from Alice relay to see current state.
48+
3. Initialize head.
49+
4. Commit at least one UTxO per participant.
50+
5. Wait for `Open`.
51+
6. Submit one simple transfer transaction. (See - [Submitting Hydra transactions](./examples/submitting-hydra-transactions.md)
52+
)
53+
7. Close and fanout.
54+
8. Verify final L1 balances.
55+
56+
See more concrete examples below:
57+
58+
## Practical examples
59+
60+
61+
- [Working with wallets](./examples/working-with-wallets.md)
62+
- [Committing UTxOs to Hydra](./examples/commiting-utxos-to-hydra.md)
63+
- [Submitting Hydra transactions](./examples/submitting-hydra-transactions.md)
64+
- [Minting native tokens](./examples/minting-native-tokens.md)
65+
- [Burning native tokens](./examples/burning-native-tokens.md)
66+
- [Paying to a script](./examples/paying-to-script.md)
67+
- [Payment to 100+ new addresses (minimum 2 ADA)](./examples/payment-to-100-addresses.md)
68+
- [Full end-to-end Hydra flow](./examples/full-end-to-end-example.md)
69+
- [Devnet cluster workflow](./examples/devnet-cluster.md)
70+
71+
## Core API references
72+
73+
- [Kuber-Hydra API reference](../kuber-hydra-api-reference.md)
74+
- [Transaction builder API (`buildTx`)](./buildTx.md)
75+
- [Hydra head status query API (`queryHeadState`)](./queryHeadState.md)
76+
- [UTxO query API](./queryUtxo.md)
77+
- [Protocol parameters query API](./queryProtocolParameters.md)
1278

79+
## Common pitfalls
1380

14-
### ⚡ Quick Start : [Local devnet](./local-devnet.md)
81+
- Head not `Open` when submitting tx: wait for state transition and retry.
82+
- Commit fails due to low balance/collateral: fund wallet and select larger UTxO.
83+
- High-fanout outputs fail: chunk outputs into multiple transactions.
84+
- Inconsistent local runs: reset devnet and rerun from a known state.
1585

16-
No need to request funds, and wait for transactions. Devnet cluster with single cardano node speeds up testing and development
86+
## Suggested route by use-case
1787

88+
- Wallet integration focus: wallets -> commit -> submit tx.
89+
- Token lifecycle focus: mint -> burn -> verify balances.
90+
- Contract flow focus: pay-to-script -> follow-up spend flow.
91+
- Throughput focus: 100+ recipient output batching.
1892

19-
### 🌐 Real public network : [Testnet/Mainnet](./testnet_or_mainnet.md)
93+
## Recommended learning path
2094

21-
Use this when you want a real-world feel. You will connect to a live Cardano network, work with real wallets. You will need real/testnet
22-
funds
95+
1. Start with [Local devnet](./local-devnet.md).
96+
2. Run [Working with wallets](./examples/working-with-wallets.md) and [Submitting Hydra transactions](./examples/submitting-hydra-transactions.md).
97+
3. Run practical advanced examples: mint, burn, pay-to-script, and high-fanout payments.
98+
4. Finish with the [Full end-to-end example](./examples/full-end-to-end-example.md).
2399

docs/sidebars.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ const sidebars: SidebarsConfig = {
9595
"hydra-js-client/examples/commiting-utxos-to-hydra",
9696
"hydra-js-client/examples/submitting-hydra-transactions",
9797
"hydra-js-client/examples/minting-native-tokens",
98+
"hydra-js-client/examples/burning-native-tokens",
99+
"hydra-js-client/examples/paying-to-script",
100+
"hydra-js-client/examples/payment-to-100-addresses",
98101
"hydra-js-client/examples/full-end-to-end-example",
99102
"hydra-js-client/examples/devnet-cluster",
100103
],

0 commit comments

Comments
 (0)