Skip to content

[Bug] BCS incompatibility: @iota/notarization buildProgrammableTransaction() output cannot be deserialized by @iota/iota-sdk Transaction #202

@SMartorana

Description

@SMartorana

BCS incompatibility: @iota/notarization buildProgrammableTransaction() output cannot be deserialized by @iota/iota-sdk Transaction

Description

When using @iota/notarization (v0.1.9) in a browser-based dApp (Next.js + @iota/dapp-kit), the BCS bytes returned by TransactionBuilder.transaction.buildProgrammableTransaction() cannot be deserialized by @iota/iota-sdk (v1.10.1).

This makes it impossible to integrate the notarization SDK with dApp-kit's useSignAndExecuteTransaction hook, since neither Transaction.from(bytes) nor Transaction.fromKind(bytes) can parse the output.

Environment

Package Version
@iota/notarization 0.1.9
@iota/iota-sdk 1.10.1
@iota/iota-interaction-ts 0.11.0 (transitive dep)
@iota/dapp-kit 0.5.1
Runtime Browser (Next.js 16, web build)

Steps to Reproduce

import { Transaction } from '@iota/iota-sdk/transactions';
import {
  NotarizationClientReadOnly,
  NotarizationBuilderLocked,
  init as initNotarizationWasm,
} from '@iota/notarization/web';

// 1. Initialize WASM
await initNotarizationWasm('/path/to/notarization_wasm_bg.wasm');

// 2. Create read-only client
const notarizationClient = await NotarizationClientReadOnly.createWithPkgId(
  iotaClient,
  NOTARIZATION_PACKAGE_ID,
);

// 3. Build locked notarization via SDK builder
const txBuilder = NotarizationBuilderLocked.locked()
  .withBytesState(hashBytes, JSON.stringify(metadata))
  .withImmutableDescription('description')
  .withUpdatableMetadata('admin metadata')
  .finish();

// 4. Get PTB bytes
const bytes = await txBuilder.transaction.buildProgrammableTransaction(notarizationClient);

// 5. Try to deserialize — BOTH fail ❌
Transaction.from(bytes);     // Error: Unknown value 5 for enum TransactionData
Transaction.fromKind(bytes); // Error: Unknown value 5 for enum TransactionKind

Expected Behavior

The BCS bytes returned by buildProgrammableTransaction() should be deserializable by Transaction.from() or Transaction.fromKind() from @iota/iota-sdk, so that dApp developers can integrate the notarization SDK with wallet-based signing flows (e.g., @iota/dapp-kit).

Actual Behavior

Both Transaction.from(bytes) and Transaction.fromKind(bytes) throw:

Error: Unknown value 5 for enum TransactionData
Error: Unknown value 5 for enum TransactionKind

This suggests the BCS schema used by @iota/notarization (via @iota/iota-interaction-ts v0.11.0) is incompatible with the BCS schema expected by @iota/iota-sdk v1.10.1.

Workaround

We are currently constructing the PTB manually using @iota/iota-sdk's Transaction class, calling the Move functions directly:

const tx = new Transaction();

// Build State<vector<u8>>
const [state] = tx.moveCall({
  target: `${NOTARIZATION_PKG}::notarization::new_state_from_bytes`,
  arguments: [
    tx.pure.vector('u8', Array.from(hashBytes)),
    tx.pure.option('string', JSON.stringify(metadata)),
  ],
});

// Build TimeLock::None
const [deleteLock] = tx.moveCall({
  target: `${NOTARIZATION_PKG}::timelock::none`,
  arguments: [],
});

// Create Locked Notarization
tx.moveCall({
  target: `${NOTARIZATION_PKG}::locked_notarization::create`,
  typeArguments: ['vector<u8>'],
  arguments: [
    state,
    tx.pure.option('string', description),
    tx.pure.option('string', adminMetadata),
    deleteLock,
    tx.object('0x6'), // Clock
  ],
});

This works but defeats the purpose of having the SDK.

Context

The @iota/notarization SDK is designed with buildAndExecute(client) for server-side flows where the SDK holds the keypair. For browser-based dApps using wallet extensions (dApp-kit), developers need to extract a signable Transaction object from the SDK, which is currently not possible due to this BCS mismatch.

Suggestion

  • Ensure that buildProgrammableTransaction() (or a new method like buildTransaction()) returns BCS bytes compatible with @iota/iota-sdk's Transaction class
  • Or provide a toTransaction(): Transaction helper that returns an @iota/iota-sdk Transaction directly
  • Or document the expected dApp-kit integration pattern

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

Status

Product Backlog

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions