iotaledger / iotaledger/notarization
[Bug] BCS incompatibility: @iota/notarization buildProgrammableTransaction() output cannot be deserialized by @iota/iota-sdk Transaction
- Dominant language
- Rust
- Stars
- 5
- Forks
- 7
- Avg merge
- 10h 34m
- Merged PRs (30d)
- 11
Description
# 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
```typescript
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()](file:///c:/GitHub/hackatonIOTA-FE/node_modules/@iota/notarization/web/notarization_wasm.d.ts#1171-1183) 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](file:///c:/GitHub/hackatonIOTA-FE/node_modules/@iota/iota-interaction-ts/web/transaction_internal.d.ts#12-17) class, calling the Move functions directly:
```typescript
const tx = new Transaction();
// Build State>
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'],
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)](file:///c:/GitHub/hackatonIOTA-FE/node_modules/@iota/iota-interaction-ts/web/transaction_internal.d.ts#28-29) 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](file:///c:/GitHub/hackatonIOTA-FE/node_modules/@iota/iota-interaction-ts/web/transaction_internal.d.ts#12-17) object from the SDK, which is currently not possible due to this BCS mismatch.
## Suggestion
- Ensure that [buildProgrammableTransaction()](file:///c:/GitHub/hackatonIOTA-FE/node_modules/@iota/notarization/web/notarization_wasm.d.ts#1171-1183) (or a new method like `buildTransaction()`) returns BCS bytes compatible with `@iota/iota-sdk`'s [Transaction](file:///c:/GitHub/hackatonIOTA-FE/node_modules/@iota/iota-interaction-ts/web/transaction_internal.d.ts#12-17) class
- Or provide a `toTransaction(): Transaction` helper that returns an `@iota/iota-sdk` [Transaction](file:///c:/GitHub/hackatonIOTA-FE/node_modules/@iota/iota-interaction-ts/web/transaction_internal.d.ts#12-17) directly
- Or document the expected dApp-kit integration pattern
Contributor guide
Assessment
This issue has not been assessed yet.