Skip to content

Commit ac83d0f

Browse files
Merge pull request #65 from IntersectMBO/feat/add-more-decoders
feat(docs): improve CBOR decoder tool UI and add data decoder option
2 parents 68ff1d3 + c4f650c commit ac83d0f

File tree

7 files changed

+218
-64
lines changed

7 files changed

+218
-64
lines changed
Lines changed: 94 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
'use client'
22

33
import { useState } from 'react'
4-
import { Core } from "@evolution-sdk/evolution"
4+
import { Core, Schema } from "@evolution-sdk/evolution"
5+
6+
type DecodeType = 'transaction' | 'witnessSet' | 'data'
57

68
export function TransactionDecoder() {
79
const [txHex, setTxHex] = useState("")
810
const [decodedJson, setDecodedJson] = useState<string>("")
911
const [error, setError] = useState<string | null>(null)
12+
const [decodeType, setDecodeType] = useState<DecodeType>('transaction')
1013

1114
const decodeTx = async () => {
1215
setError(null)
@@ -16,60 +19,114 @@ export function TransactionDecoder() {
1619
const cleanHex = txHex.trim().replace(/\s+/g, '')
1720

1821
if (!cleanHex) {
19-
setError("Please enter a transaction CBOR hex string")
22+
setError(`Please enter a ${decodeType === 'transaction' ? 'transaction' : decodeType === 'witnessSet' ? 'transaction witness set' : 'plutus data'} CBOR hex string`)
2023
return
2124
}
2225

23-
const tx = Core.Transaction.fromCBORHex(cleanHex)
24-
const json = JSON.stringify(tx.toJSON(), (key, value) =>
25-
typeof value === 'bigint' ? value.toString() : value
26-
, 2)
27-
setDecodedJson(json)
26+
if (decodeType === 'transaction') {
27+
const tx = Core.Transaction.fromCBORHex(cleanHex)
28+
const json = Schema.encodeSync(Schema.parseJson(Core.Transaction.Transaction, {space: 2}))(tx)
29+
setDecodedJson(json)
30+
} else if (decodeType === 'witnessSet') {
31+
const witnessSet = Core.TransactionWitnessSet.fromCBORHex(cleanHex)
32+
const json = Schema.encodeSync(Schema.parseJson(Core.TransactionWitnessSet.TransactionWitnessSet, {space: 2}))(witnessSet)
33+
setDecodedJson(json)
34+
} else {
35+
const data = Core.Data.fromCBORHex(cleanHex)
36+
const json = Schema.encodeSync(Schema.parseJson(Core.Data.DataSchema, {space: 2}))(data)
37+
setDecodedJson(json)
38+
}
2839
} catch (err) {
2940
console.error('Decode error:', err)
30-
setError(err instanceof Error ? err.message : "Failed to decode transaction")
41+
setError(err instanceof Error ? err.message : `Failed to decode ${decodeType === 'transaction' ? 'transaction' : decodeType === 'witnessSet' ? 'witness set' : 'data'}`)
3142
}
3243
}
3344

3445
return (
35-
<div className="space-y-6">
36-
<div className="space-y-4">
37-
<button
38-
onClick={decodeTx}
39-
className="px-4 py-2 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors"
40-
>
41-
Decode Transaction
42-
</button>
43-
44-
<div className="space-y-2">
45-
<label htmlFor="tx-hex" className="block text-sm font-medium">
46-
Transaction CBOR Hex
47-
</label>
48-
<textarea
49-
id="tx-hex"
50-
value={txHex}
51-
onChange={(e) => setTxHex(e.target.value)}
52-
placeholder="Paste transaction CBOR hex here..."
53-
className="w-full h-32 px-3 py-2 bg-background border border-border rounded-md font-mono text-sm resize-y focus:outline-none focus:ring-2 focus:ring-ring"
54-
/>
46+
<div className="max-w-6xl mx-auto space-y-6">
47+
<div className="rounded-lg border bg-card text-card-foreground shadow-sm">
48+
<div className="p-6 space-y-6">
49+
<div className="flex items-center justify-between">
50+
<div className="space-y-1">
51+
<h3 className="text-2xl font-semibold tracking-tight">CBOR Decoder</h3>
52+
<p className="text-sm text-muted-foreground">Decode Cardano CBOR hex strings</p>
53+
</div>
54+
</div>
55+
56+
<div className="space-y-4">
57+
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
58+
<div className="space-y-2">
59+
<label htmlFor="decode-type" className="text-sm font-medium leading-none">
60+
Type
61+
</label>
62+
<select
63+
id="decode-type"
64+
value={decodeType}
65+
onChange={(e) => setDecodeType(e.target.value as DecodeType)}
66+
className="flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring"
67+
>
68+
<option value="transaction">Transaction</option>
69+
<option value="witnessSet">Transaction Witness Set</option>
70+
<option value="data">Plutus Data</option>
71+
</select>
72+
</div>
73+
</div>
74+
75+
<div className="space-y-2">
76+
<label htmlFor="tx-hex" className="text-sm font-medium leading-none">
77+
CBOR Hex Input
78+
</label>
79+
<textarea
80+
id="tx-hex"
81+
value={txHex}
82+
onChange={(e) => setTxHex(e.target.value)}
83+
placeholder={`Paste ${decodeType === 'transaction' ? 'transaction' : decodeType === 'witnessSet' ? 'transaction witness set' : 'plutus data'} CBOR hex here...`}
84+
className="flex min-h-[120px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm font-mono resize-y focus:outline-none focus:ring-2 focus:ring-ring"
85+
/>
86+
</div>
87+
88+
<button
89+
onClick={decodeTx}
90+
className="sm:w-auto w-full inline-flex items-center justify-center rounded-md text-sm font-medium h-9 px-6 py-2 bg-zinc-700 text-white hover:bg-zinc-600 active:bg-zinc-500 transition-all cursor-pointer shadow-sm hover:shadow"
91+
>
92+
Decode {decodeType === 'transaction' ? 'Transaction' : decodeType === 'witnessSet' ? 'Witness Set' : 'Data'}
93+
</button>
94+
</div>
5595
</div>
5696
</div>
5797

5898
{error && (
59-
<div className="p-4 bg-destructive/10 border border-destructive/20 rounded-md">
60-
<p className="text-destructive font-medium">Error decoding transaction:</p>
61-
<p className="text-destructive/80 text-sm mt-1">{error}</p>
99+
<div className="rounded-lg border bg-card text-card-foreground shadow-sm">
100+
<div className="p-6">
101+
<div className="flex gap-3">
102+
<svg className="h-5 w-5 text-destructive shrink-0 mt-0.5" viewBox="0 0 20 20" fill="currentColor">
103+
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clipRule="evenodd" />
104+
</svg>
105+
<div className="flex-1 min-w-0 space-y-2">
106+
<p className="text-sm font-medium text-destructive">Error decoding {decodeType === 'transaction' ? 'transaction' : decodeType === 'witnessSet' ? 'witness set' : 'data'}</p>
107+
<pre className="text-xs text-muted-foreground whitespace-pre-wrap break-words overflow-wrap-anywhere font-mono">{error}</pre>
108+
</div>
109+
</div>
110+
</div>
62111
</div>
63112
)}
64-
113+
65114
{decodedJson && (
66-
<div className="space-y-2">
67-
<label className="block text-sm font-medium">Decoded Transaction (JSON)</label>
68-
<pre className="w-full p-4 bg-muted border border-border rounded-md overflow-auto max-h-[600px] text-sm">
69-
<code>{decodedJson}</code>
70-
</pre>
115+
<div className="rounded-lg border bg-card text-card-foreground shadow-sm">
116+
<div className="p-6 space-y-3">
117+
<h4 className="text-sm font-semibold">Decoded Result</h4>
118+
<pre className="rounded-md bg-muted p-4 overflow-x-auto max-h-[500px]">
119+
<code className="text-xs">{decodedJson}</code>
120+
</pre>
121+
</div>
71122
</div>
72123
)}
124+
125+
<div className="pt-4 border-t border-border/50">
126+
<p className="text-xs text-center text-muted-foreground">
127+
Questions or feedback? <a href="https://github.com/IntersectMBO/evolution-sdk/issues" target="_blank" rel="noopener noreferrer" className="text-primary hover:underline">Start a discussion on GitHub</a>
128+
</p>
129+
</div>
73130
</div>
74131
)
75132
}

docs/content/docs/modules/core/CBOR.mdx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ parent: Modules
1111
<h2 className="text-delta">Table of contents</h2>
1212

1313
- [constants](#constants)
14+
- [AIKEN_DEFAULT_OPTIONS](#aiken_default_options)
1415
- [CANONICAL_OPTIONS](#canonical_options)
1516
- [CBOR_ADDITIONAL_INFO](#cbor_additional_info)
1617
- [CBOR_MAJOR_TYPE](#cbor_major_type)
@@ -64,6 +65,25 @@ parent: Modules
6465

6566
# constants
6667

68+
## AIKEN_DEFAULT_OPTIONS
69+
70+
Aiken-compatible CBOR encoding options
71+
72+
Matches the encoding used by Aiken's cbor.serialise():
73+
74+
- Indefinite-length arrays (9f...ff)
75+
- Maps encoded as arrays of pairs (not CBOR maps)
76+
- Strings as bytearrays (major type 2, not 3)
77+
- Constructor tags: 121-127 for indices 0-6, then 1280+ for 7+
78+
79+
**Signature**
80+
81+
```ts
82+
export declare const AIKEN_DEFAULT_OPTIONS: CodecOptions
83+
```
84+
85+
Added in v2.0.0
86+
6787
## CANONICAL_OPTIONS
6888
6989
Canonical CBOR encoding options (RFC 8949 Section 4.2.1)
@@ -239,6 +259,7 @@ export type CodecOptions =
239259
| {
240260
readonly mode: "canonical"
241261
readonly mapsAsObjects?: boolean
262+
readonly encodeMapAsPairs?: boolean
242263
}
243264
| {
244265
readonly mode: "custom"
@@ -248,6 +269,7 @@ export type CodecOptions =
248269
readonly sortMapKeys: boolean
249270
readonly useMinimalEncoding: boolean
250271
readonly mapsAsObjects?: boolean
272+
readonly encodeMapAsPairs?: boolean
251273
}
252274
```
253275

docs/content/docs/modules/core/Data.mdx

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ parent: Modules
2020
- [int](#int)
2121
- [list](#list)
2222
- [map](#map)
23-
- [either](#either)
24-
- [Either (namespace)](#either-namespace)
2523
- [equality](#equality)
2624
- [equals](#equals)
2725
- [hash](#hash)
@@ -71,6 +69,7 @@ parent: Modules
7169
- [utils](#utils)
7270
- [ByteArray (type alias)](#bytearray-type-alias)
7371
- [CDDLSchema](#cddlschema)
72+
- [DataSchema (interface)](#dataschema-interface)
7473
- [Int (type alias)](#int-type-alias)
7574

7675
---
@@ -88,12 +87,12 @@ export declare const withSchema: <A, I extends Data>(
8887
schema: Schema.Schema<A, I>,
8988
options?: CBOR.CodecOptions
9089
) => {
91-
toData: (input: A) => I
92-
fromData: (input: I) => A
93-
toCBORHex: (input: A, options?: CBOR.CodecOptions) => string
94-
toCBORBytes: (input: A, options?: CBOR.CodecOptions) => Uint8Array
95-
fromCBORHex: (hex: string, options?: CBOR.CodecOptions) => A
96-
fromCBORBytes: (bytes: Uint8Array, options?: CBOR.CodecOptions) => A
90+
toData: (a: A, overrideOptions?: ParseOptions) => I
91+
fromData: (i: I, overrideOptions?: ParseOptions) => A
92+
toCBORHex: (a: A, overrideOptions?: ParseOptions) => string
93+
toCBORBytes: (a: A, overrideOptions?: ParseOptions) => any
94+
fromCBORHex: (i: string, overrideOptions?: ParseOptions) => A
95+
fromCBORBytes: (i: any, overrideOptions?: ParseOptions) => A
9796
}
9897
```
9998
@@ -175,14 +174,6 @@ export declare const map: (entries: Array<[key: Data, value: Data]>) => Map
175174
176175
Added in v2.0.0
177176
178-
# either
179-
180-
## Either (namespace)
181-
182-
Either-based variants for functions that can fail.
183-
184-
Added in v2.0.0
185-
186177
# equality
187178
188179
## equals
@@ -525,7 +516,7 @@ Combined schema for PlutusData type with proper recursion
525516
**Signature**
526517

527518
```ts
528-
export declare const DataSchema: Schema.Schema<Data, DataEncoded, never>
519+
export declare const DataSchema: DataSchema
529520
```
530521

531522
Added in v2.0.0
@@ -735,7 +726,7 @@ Encode PlutusData to CBOR bytes
735726
**Signature**
736727
737728
```ts
738-
export declare const toCBORBytes: (input: Data, options?: CBOR.CodecOptions) => Uint8Array
729+
export declare const toCBORBytes: (data: Data, options?: CBOR.CodecOptions) => any
739730
```
740731
741732
Added in v2.0.0
@@ -747,7 +738,7 @@ Encode PlutusData to CBOR hex string
747738
**Signature**
748739
749740
```ts
750-
export declare const toCBORHex: (input: Data, options?: CBOR.CodecOptions) => string
741+
export declare const toCBORHex: (data: Data, options?: CBOR.CodecOptions) => string
751742
```
752743
753744
Added in v2.0.0
@@ -808,6 +799,14 @@ export type ByteArray = typeof ByteArray.Type
808799
export declare const CDDLSchema: Schema.Schema<CBOR.CBOR, CBOR.CBOR, never>
809800
```
810801
802+
## DataSchema (interface)
803+
804+
**Signature**
805+
806+
```ts
807+
export interface DataSchema extends Schema.SchemaClass<Data, DataEncoded> {}
808+
```
809+
811810
## Int (type alias)
812811

813812
**Signature**

0 commit comments

Comments
 (0)