From 94605c779ac42584dda69c942f4e6ed86fc89759 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 5 Dec 2025 13:50:13 +0000 Subject: [PATCH 1/6] Initial plan From 5f81b9c28b7afda90f8573c2a48a5a7040a30baf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 5 Dec 2025 13:59:43 +0000 Subject: [PATCH 2/6] Add unwrapped object type support to SDK and explorer Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> --- apps/core/src/types/objectChange.ts | 1 + apps/core/src/utils/transaction/getObjectChangeLabel.ts | 1 + .../core/src/utils/transaction/getObjectChangeSummary.ts | 5 +++++ .../transaction-result/transaction-summary/index.tsx | 1 + sdk/graphql-transport/src/mappers/transaction-block.ts | 4 +++- sdk/typescript/src/client/types/changes.ts | 1 + sdk/typescript/src/client/types/generated.ts | 9 +++++++++ 7 files changed, 21 insertions(+), 1 deletion(-) diff --git a/apps/core/src/types/objectChange.ts b/apps/core/src/types/objectChange.ts index 5c1c878e61d..8e135f21f3a 100644 --- a/apps/core/src/types/objectChange.ts +++ b/apps/core/src/types/objectChange.ts @@ -9,6 +9,7 @@ export type IotaObjectChangeTypes = | 'mutated' | 'deleted' | 'wrapped' + | 'unwrapped' | 'created'; export type WithDisplayFields = T & { display?: DisplayFieldsResponse }; diff --git a/apps/core/src/utils/transaction/getObjectChangeLabel.ts b/apps/core/src/utils/transaction/getObjectChangeLabel.ts index 4ee974c9e92..239534c2d16 100644 --- a/apps/core/src/utils/transaction/getObjectChangeLabel.ts +++ b/apps/core/src/utils/transaction/getObjectChangeLabel.ts @@ -11,6 +11,7 @@ export const ObjectChangeLabels = { published: 'Publish', deleted: 'Deleted', wrapped: 'Wrap', + unwrapped: 'Unwrap', }; export function getObjectChangeLabel(type: IotaObjectChangeTypes) { diff --git a/apps/core/src/utils/transaction/getObjectChangeSummary.ts b/apps/core/src/utils/transaction/getObjectChangeSummary.ts index 8635f3f911d..9e0b6d3fb6f 100644 --- a/apps/core/src/utils/transaction/getObjectChangeSummary.ts +++ b/apps/core/src/utils/transaction/getObjectChangeSummary.ts @@ -36,6 +36,10 @@ export const getObjectChangeSummary = (objectChanges: IotaObjectChangeWithDispla (change) => change.type === 'wrapped', ) as IotaObjectChangeWrapped[]; + const unwrapped = objectChanges.filter( + (change) => change.type === 'unwrapped', + ) as IotaObjectChangeWithDisplay[]; + const deleted = objectChanges.filter( (change) => change.type === 'deleted', ) as IotaObjectChangeDeleted[]; @@ -46,6 +50,7 @@ export const getObjectChangeSummary = (objectChanges: IotaObjectChangeWithDispla mutated: groupByOwner(mutated), published: groupByOwner(published), wrapped: groupByOwner(wrapped), + unwrapped: groupByOwner(unwrapped), deleted: groupByOwner(deleted), }; }; diff --git a/apps/explorer/src/pages/transaction-result/transaction-summary/index.tsx b/apps/explorer/src/pages/transaction-result/transaction-summary/index.tsx index 99f60527c08..57bfcf17ce4 100644 --- a/apps/explorer/src/pages/transaction-result/transaction-summary/index.tsx +++ b/apps/explorer/src/pages/transaction-result/transaction-summary/index.tsx @@ -51,6 +51,7 @@ const EMPTY_OBJECT_SUMMARY: ObjectChangeSummary = { mutated: {}, deleted: {}, wrapped: {}, + unwrapped: {}, created: {}, }; diff --git a/sdk/graphql-transport/src/mappers/transaction-block.ts b/sdk/graphql-transport/src/mappers/transaction-block.ts index 075199e4672..cec57b84ad4 100644 --- a/sdk/graphql-transport/src/mappers/transaction-block.ts +++ b/sdk/graphql-transport/src/mappers/transaction-block.ts @@ -161,13 +161,15 @@ function mapObjectChanges( effects?.unwrapped?.forEach((unwrapped) => { changes.push({ - type: 'wrapped', + type: 'unwrapped', + digest: unwrapped.reference.digest, objectId: unwrapped.reference.objectId, objectType: toShortTypeString( transactionBlock.effects?.objectChanges?.nodes.find( (change) => change.address === unwrapped.reference.objectId, )?.outputState?.asMoveObject?.contents?.type.repr!, ), + owner: unwrapped.owner, sender: transactionBlock.sender?.address!, version: unwrapped.reference.version?.toString(), }); diff --git a/sdk/typescript/src/client/types/changes.ts b/sdk/typescript/src/client/types/changes.ts index 8d272dec19d..69d1bb72987 100644 --- a/sdk/typescript/src/client/types/changes.ts +++ b/sdk/typescript/src/client/types/changes.ts @@ -9,4 +9,5 @@ export type IotaObjectChangeTransferred = Extract; export type IotaObjectChangeDeleted = Extract; export type IotaObjectChangeWrapped = Extract; +export type IotaObjectChangeUnwrapped = Extract; export type IotaObjectChangeCreated = Extract; diff --git a/sdk/typescript/src/client/types/generated.ts b/sdk/typescript/src/client/types/generated.ts index 5b25bf6f1a5..07b0de4153c 100644 --- a/sdk/typescript/src/client/types/generated.ts +++ b/sdk/typescript/src/client/types/generated.ts @@ -1223,6 +1223,15 @@ export type IotaObjectChange = sender: string; type: 'wrapped'; version: string; + } /** Unwrapped object */ + | { + digest: string; + objectId: string; + objectType: string; + owner: ObjectOwner; + sender: string; + type: 'unwrapped'; + version: string; } /** New object creation */ | { digest: string; From 0f7b7b70f967a1615eee6436dc5039d5df5decc9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 5 Dec 2025 14:06:12 +0000 Subject: [PATCH 3/6] Verify all changes for unwrapped objects support Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> --- sdk/typescript/src/version.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/typescript/src/version.ts b/sdk/typescript/src/version.ts index 9917024522b..349c6cbf448 100644 --- a/sdk/typescript/src/version.ts +++ b/sdk/typescript/src/version.ts @@ -5,4 +5,4 @@ // This file is generated by genversion.mjs. Do not edit it directly. export const PACKAGE_VERSION = '1.9.0'; -export const TARGETED_RPC_VERSION = '1.13.0-alpha'; +export const TARGETED_RPC_VERSION = '1.14.0-alpha'; From 94e867add8c24985fba87ee4e9284c179d66e656 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 5 Dec 2025 14:07:48 +0000 Subject: [PATCH 4/6] Use IotaObjectChangeUnwrapped type for consistency Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> --- apps/core/src/utils/transaction/getObjectChangeSummary.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/core/src/utils/transaction/getObjectChangeSummary.ts b/apps/core/src/utils/transaction/getObjectChangeSummary.ts index 9e0b6d3fb6f..04de1406eae 100644 --- a/apps/core/src/utils/transaction/getObjectChangeSummary.ts +++ b/apps/core/src/utils/transaction/getObjectChangeSummary.ts @@ -7,6 +7,7 @@ import { IotaObjectChangeMutated, IotaObjectChangePublished, IotaObjectChangeTransferred, + IotaObjectChangeUnwrapped, IotaObjectChangeWrapped, } from '@iota/iota-sdk/client'; @@ -38,7 +39,7 @@ export const getObjectChangeSummary = (objectChanges: IotaObjectChangeWithDispla const unwrapped = objectChanges.filter( (change) => change.type === 'unwrapped', - ) as IotaObjectChangeWithDisplay[]; + ) as IotaObjectChangeUnwrapped[]; const deleted = objectChanges.filter( (change) => change.type === 'deleted', From 55eb4348346e962b4ad375e7cee92ac64a29148d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 5 Dec 2025 15:15:32 +0000 Subject: [PATCH 5/6] Add Unwrapped variant to Rust ObjectChange enum - Added Unwrapped variant to ObjectChange enum in iota-json-rpc-types - Updated all match statements to handle Unwrapped objects - Added WriteKind::Unwrap handling in object_changes.rs - Updated Display implementation for Unwrapped objects - Reverted manual changes to generated TypeScript files Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> --- .../src/iota_transaction.rs | 5 ++- .../iota-json-rpc-types/src/object_changes.rs | 43 +++++++++++++++++++ crates/iota-json-rpc/src/object_changes.rs | 8 ++++ crates/iota/src/displays/dry_run_tx_block.rs | 5 ++- sdk/typescript/src/client/types/generated.ts | 9 ---- sdk/typescript/src/version.ts | 2 +- 6 files changed, 60 insertions(+), 12 deletions(-) diff --git a/crates/iota-json-rpc-types/src/iota_transaction.rs b/crates/iota-json-rpc-types/src/iota_transaction.rs index de1d719266c..0b3a1ff7549 100644 --- a/crates/iota-json-rpc-types/src/iota_transaction.rs +++ b/crates/iota-json-rpc-types/src/iota_transaction.rs @@ -334,7 +334,8 @@ impl Display for IotaTransactionBlockResponse { mut published, mut transferred, mut wrapped, - ) = (vec![], vec![], vec![], vec![], vec![], vec![]); + mut unwrapped, + ) = (vec![], vec![], vec![], vec![], vec![], vec![], vec![]); for obj in object_changes { match obj { @@ -344,6 +345,7 @@ impl Display for IotaTransactionBlockResponse { ObjectChange::Published { .. } => published.push(obj), ObjectChange::Transferred { .. } => transferred.push(obj), ObjectChange::Wrapped { .. } => wrapped.push(obj), + ObjectChange::Unwrapped { .. } => unwrapped.push(obj), }; } @@ -353,6 +355,7 @@ impl Display for IotaTransactionBlockResponse { write_obj_changes(published, "Published", &mut builder)?; write_obj_changes(transferred, "Transferred", &mut builder)?; write_obj_changes(wrapped, "Wrapped", &mut builder)?; + write_obj_changes(unwrapped, "Unwrapped", &mut builder)?; let mut table = builder.build(); table.with(TablePanel::header("Object Changes")); diff --git a/crates/iota-json-rpc-types/src/object_changes.rs b/crates/iota-json-rpc-types/src/object_changes.rs index 6141c99b69d..61be19d4902 100644 --- a/crates/iota-json-rpc-types/src/object_changes.rs +++ b/crates/iota-json-rpc-types/src/object_changes.rs @@ -85,6 +85,20 @@ pub enum ObjectChange { #[serde_as(as = "AsSequenceNumber")] version: SequenceNumber, }, + /// Unwrapped object + #[serde(rename_all = "camelCase")] + Unwrapped { + sender: IotaAddress, + owner: Owner, + #[schemars(with = "String")] + #[serde_as(as = "IotaStructTag")] + object_type: StructTag, + object_id: ObjectID, + #[schemars(with = "AsSequenceNumber")] + #[serde_as(as = "AsSequenceNumber")] + version: SequenceNumber, + digest: ObjectDigest, + }, /// New object creation #[serde(rename_all = "camelCase")] Created { @@ -109,6 +123,7 @@ impl ObjectChange { | ObjectChange::Mutated { object_id, .. } | ObjectChange::Deleted { object_id, .. } | ObjectChange::Wrapped { object_id, .. } + | ObjectChange::Unwrapped { object_id, .. } | ObjectChange::Created { object_id, .. } => *object_id, } } @@ -133,6 +148,12 @@ impl ObjectChange { digest, .. } + | ObjectChange::Unwrapped { + object_id, + version, + digest, + .. + } | ObjectChange::Created { object_id, version, @@ -159,6 +180,9 @@ impl ObjectChange { | ObjectChange::Mutated { version, digest, .. } + | ObjectChange::Unwrapped { + version, digest, .. + } | ObjectChange::Created { version, digest, .. } => { @@ -259,6 +283,25 @@ impl Display for ObjectChange { u64::from(*version) ) } + ObjectChange::Unwrapped { + sender, + owner, + object_type, + object_id, + version, + digest, + } => { + write!( + f, + " ┌──\n │ ObjectID: {}\n │ Sender: {} \n │ Owner: {}\n │ ObjectType: {} \n │ Version: {}\n │ Digest: {}\n └──", + object_id, + sender, + owner, + object_type, + u64::from(*version), + digest + ) + } ObjectChange::Created { sender, owner, diff --git a/crates/iota-json-rpc/src/object_changes.rs b/crates/iota-json-rpc/src/object_changes.rs index 63ea01b2970..f204848ab34 100644 --- a/crates/iota-json-rpc/src/object_changes.rs +++ b/crates/iota-json-rpc/src/object_changes.rs @@ -52,6 +52,14 @@ pub async fn get_object_changes, E>( version, digest, }), + WriteKind::Unwrap => object_changes.push(ObjectChange::Unwrapped { + sender, + owner, + object_type, + object_id, + version, + digest, + }), _ => {} } } else if let Some(p) = o.data.try_as_package() { diff --git a/crates/iota/src/displays/dry_run_tx_block.rs b/crates/iota/src/displays/dry_run_tx_block.rs index 107729ed254..f9d6f21e402 100644 --- a/crates/iota/src/displays/dry_run_tx_block.rs +++ b/crates/iota/src/displays/dry_run_tx_block.rs @@ -49,7 +49,8 @@ impl Display for Pretty<'_, DryRunTransactionBlockResponse> { mut published, mut transferred, mut wrapped, - ) = (vec![], vec![], vec![], vec![], vec![], vec![]); + mut unwrapped, + ) = (vec![], vec![], vec![], vec![], vec![], vec![], vec![]); for obj in &response.object_changes { match obj { ObjectChange::Created { .. } => created.push(obj), @@ -58,6 +59,7 @@ impl Display for Pretty<'_, DryRunTransactionBlockResponse> { ObjectChange::Published { .. } => published.push(obj), ObjectChange::Transferred { .. } => transferred.push(obj), ObjectChange::Wrapped { .. } => wrapped.push(obj), + ObjectChange::Unwrapped { .. } => unwrapped.push(obj), }; } @@ -67,6 +69,7 @@ impl Display for Pretty<'_, DryRunTransactionBlockResponse> { write_obj_changes(published, "Published", &mut builder)?; write_obj_changes(transferred, "Transferred", &mut builder)?; write_obj_changes(wrapped, "Wrapped", &mut builder)?; + write_obj_changes(unwrapped, "Unwrapped", &mut builder)?; let mut table = builder.build(); table.with(TablePanel::header("Object Changes")); diff --git a/sdk/typescript/src/client/types/generated.ts b/sdk/typescript/src/client/types/generated.ts index 07b0de4153c..5b25bf6f1a5 100644 --- a/sdk/typescript/src/client/types/generated.ts +++ b/sdk/typescript/src/client/types/generated.ts @@ -1223,15 +1223,6 @@ export type IotaObjectChange = sender: string; type: 'wrapped'; version: string; - } /** Unwrapped object */ - | { - digest: string; - objectId: string; - objectType: string; - owner: ObjectOwner; - sender: string; - type: 'unwrapped'; - version: string; } /** New object creation */ | { digest: string; diff --git a/sdk/typescript/src/version.ts b/sdk/typescript/src/version.ts index 349c6cbf448..9917024522b 100644 --- a/sdk/typescript/src/version.ts +++ b/sdk/typescript/src/version.ts @@ -5,4 +5,4 @@ // This file is generated by genversion.mjs. Do not edit it directly. export const PACKAGE_VERSION = '1.9.0'; -export const TARGETED_RPC_VERSION = '1.14.0-alpha'; +export const TARGETED_RPC_VERSION = '1.13.0-alpha'; From 7c935358c0e34c7140636295555e724e423e7a96 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 8 Dec 2025 08:27:04 +0000 Subject: [PATCH 6/6] Add missing wrapped objects handling in GraphQL mapper The original code was incorrectly mapping unwrapped objects as wrapped. Now both are handled correctly: - unwrapped objects (from effects.unwrapped) -> type: 'unwrapped' - wrapped objects (from effects.wrapped) -> type: 'wrapped' Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> --- .../src/mappers/transaction-block.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sdk/graphql-transport/src/mappers/transaction-block.ts b/sdk/graphql-transport/src/mappers/transaction-block.ts index cec57b84ad4..cab1fafd0b4 100644 --- a/sdk/graphql-transport/src/mappers/transaction-block.ts +++ b/sdk/graphql-transport/src/mappers/transaction-block.ts @@ -175,6 +175,20 @@ function mapObjectChanges( }); }); + effects?.wrapped?.forEach((wrapped) => { + changes.push({ + type: 'wrapped', + objectId: wrapped.objectId, + objectType: toShortTypeString( + transactionBlock.effects?.objectChanges?.nodes.find( + (change) => change.address === wrapped.objectId, + )?.inputState?.asMoveObject?.contents?.type.repr!, + ), + sender: transactionBlock.sender?.address!, + version: wrapped.version?.toString(), + }); + }); + return changes; }