Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions bindings/go/examples/execute_transaction/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// Copyright (c) 2025 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

package main

import (
"log"

sdk "bindings/iota_sdk_ffi"
)

func main() {
client := sdk.GraphQlClientNewTestnet()

// some fix values on Testnet
privateKeyHex := "0032e67709569b6a1ef551ea7a745aac943b2158fc862ae7c6d08dd1744e15d818"
senderAddressHex := "0x786dff8a4ee13d45b502c8f22f398e3517e6ec78aa4ae564c348acb07fad7f50"
coinObjectIdHex := "0x7714345721694a20c6e2e04a6a289b1c08710cda863f7dd49b4661cde524103d"
gasObjectIdHex := "0xd7913b6c9c1e67c281ad13bffcb4d172ffb8f5a85581e5d5984eacb310365be8"

// Load keypair from hex using SimpleKeypair
privateKeyBytes, err := sdk.HexDecode(privateKeyHex)
if err != nil {
log.Fatalf("Failed to decode private key: %v", err)
}

simpleKeypair, err := sdk.SimpleKeypairFromBytes(privateKeyBytes)
if err != nil {
log.Fatalf("Failed to load private key: %v", err)
}

fromAddress, _ := sdk.AddressFromHex(senderAddressHex)
toAddress, _ := sdk.AddressFromHex(senderAddressHex)
coinObjId, _ := sdk.ObjectIdFromHex(coinObjectIdHex)
gasCoinObjId, _ := sdk.ObjectIdFromHex(gasObjectIdHex)

log.Printf("Building transaction from %s to %s\n", fromAddress.ToHex(), toAddress.ToHex())

// Build the transaction
builder := sdk.TransactionBuilderInit(fromAddress, client)
builder.TransferObjects(toAddress, []*sdk.PtbArgument{sdk.PtbArgumentObjectId(coinObjId)})
builder.Gas(gasCoinObjId).GasBudget(1000000000)

// Finish building to get the transaction
txn, err := builder.Finish()
if err.(*sdk.SdkFfiError) != nil {
log.Fatalf("Failed to build transaction: %v", err)
}

log.Printf("Transaction built, signing with keypair...\n")

// Sign the transaction using SimpleKeypair
simpleSignature, err := simpleKeypair.TrySign(txn.SigningDigest())
if err != nil {
log.Fatalf("Failed to sign transaction: %v", err)
}

// Convert SimpleSignature to UserSignature
userSignature := sdk.UserSignatureNewSimple(simpleSignature)

log.Printf("Transaction signed, executing on-chain...\n")

// Execute the transaction on-chain
effects, err := client.ExecuteTx([]*sdk.UserSignature{userSignature}, txn)
if err.(*sdk.SdkFfiError) != nil {
log.Fatalf("ExecuteTx failed: %v", err)
}

if effects == nil {
log.Println("No transaction effects returned")
return
}

log.Printf("Transaction executed successfully!\n")

// Access and print transaction effects
PrintObjectChanges(*effects)
}

func PrintObjectChanges(effects *sdk.TransactionEffects) {
log.Println("=== Object Changes (from ExecuteTx) ===")

if !effects.IsV1() {
log.Panicln("Effects version is not V1")
}

effectsV1 := effects.AsV1()
log.Printf("Total changed objects: %d\n", len(effectsV1.ChangedObjects))

for i, change := range effectsV1.ChangedObjects {
log.Printf("Object #%d:\n", i+1)
log.Printf(" Object ID: %s\n", change.ObjectId.ToHex())

// Check creation/deletion status using IdOperation
switch change.IdOperation {
case sdk.IdOperationCreated:
log.Println(" Status: CREATED")
case sdk.IdOperationDeleted:
log.Println(" Status: DELETED")
case sdk.IdOperationNone:
log.Println(" Status: MODIFIED")
}

// Object type (if available)
if change.ObjectType != nil {
log.Printf(" Type: %s\n", *change.ObjectType)
} else {
log.Printf(" Type: %v\n", change.ObjectType)
}

// Input state (state before transaction)
switch input := change.InputState.(type) {
case sdk.ObjectInMissing:
log.Println(" Input State: Missing (new object)")
case sdk.ObjectInData:
log.Printf(" Input State: Version=%d, Owner=%s\n", input.Version, input.Owner.String())
}

// Output state (state after transaction)
switch output := change.OutputState.(type) {
case sdk.ObjectOutMissing:
log.Println(" Output State: Missing (deleted)")
case sdk.ObjectOutObjectWrite:
log.Printf(" Output State: ObjectWrite, Owner=%s\n", output.Owner.String())
case sdk.ObjectOutPackageWrite:
log.Printf(" Output State: PackageWrite, Version=%d\n", output.Version)
}
}
}
102 changes: 102 additions & 0 deletions bindings/go/examples/execute_transaction_dry_run/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// Copyright (c) 2025 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

package main

import (
"log"

sdk "bindings/iota_sdk_ffi"
)

// === DryRun with ObjectChange Example ===
// This example demonstrates the ObjectChange feature using DryRun,
// which simulates transaction execution without actual on-chain changes.
func main() {

// Initialize client
client := sdk.GraphQlClientNewDevnet()

// Use actual addresses from devnet (these are examples)
fromAddress, _ := sdk.AddressFromHex("0x611830d3641a68f94a690dcc25d1f4b0dac948325ac18f6dd32564371735f32c")

toAddress, _ := sdk.AddressFromHex("0x0000a4984bd495d4346fa208ddff4f5d5e5ad48c21dec631ddebc99809f16900")

coinObjId, _ := sdk.ObjectIdFromHex("0xd04077fe3b6fad13b3d4ed0d535b7ca92afcac8f0f2a0e0925fb9f4f0b30c699")

gasCoinObjId, _ := sdk.ObjectIdFromHex("0x0b0270ee9d27da0db09651e5f7338dfa32c7ee6441ccefa1f6e305735bcfc7ab")

builder := sdk.TransactionBuilderInit(fromAddress, client)
builder.TransferObjects(toAddress, []*sdk.PtbArgument{sdk.PtbArgumentObjectId(coinObjId)})
builder.Gas(gasCoinObjId).GasBudget(1000000000)

dryRunResult, err := builder.DryRun(false)
if err.(*sdk.SdkFfiError) != nil {
log.Fatalf("Dry run failed: %v", err)
}

if dryRunResult.Error != nil {
log.Fatalf("Dry run returned an error: %s\n", *dryRunResult.Error)
}

log.Printf("Dry run succeeded!\n")

// Access transaction effects from dry run
if dryRunResult.Effects != nil {
PrintObjectChanges(*dryRunResult.Effects)
} else {
log.Println("No transaction effects available in dry run result")
}
}

func PrintObjectChanges(effects *sdk.TransactionEffects) {
log.Println("=== Object Changes (from DryRun) ===")

if !effects.IsV1() {
log.Println("Effects version is not V1")
return
}

effectsV1 := effects.AsV1()
log.Printf("Total changed objects: %d\n", len(effectsV1.ChangedObjects))

for i, change := range effectsV1.ChangedObjects {
log.Printf("Object #%d:\n", i+1)
log.Printf(" Object ID: %s\n", change.ObjectId.ToHex())

// Check creation/deletion status using IdOperation
switch change.IdOperation {
case sdk.IdOperationCreated:
log.Println(" Status: CREATED")
case sdk.IdOperationDeleted:
log.Println(" Status: DELETED")
case sdk.IdOperationNone:
log.Println(" Status: MODIFIED")
}

// Object type (if available)
if change.ObjectType != nil {
log.Printf(" Type: %s\n", *change.ObjectType)
} else {
log.Printf(" Type: %v\n", change.ObjectType)
}

// Input state (state before transaction)
switch input := change.InputState.(type) {
case sdk.ObjectInMissing:
log.Println(" Input State: Missing (new object)")
case sdk.ObjectInData:
log.Printf(" Input State: Version=%d, Owner=%s\n", input.Version, input.Owner.String())
}

// Output state (state after transaction)
switch output := change.OutputState.(type) {
case sdk.ObjectOutMissing:
log.Println(" Output State: Missing (deleted)")
case sdk.ObjectOutObjectWrite:
log.Printf(" Output State: ObjectWrite, Owner=%s\n", output.Owner.String())
case sdk.ObjectOutPackageWrite:
log.Printf(" Output State: PackageWrite, Version=%d\n", output.Version)
}
}
}
8 changes: 3 additions & 5 deletions bindings/go/examples/prepare_split_coins/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ func main() {
sender,
[]*sdk.PtbArgument{sdk.PtbArgumentRes("coin1"), sdk.PtbArgumentRes("coin2"), sdk.PtbArgumentRes("coin3")},
)
builder.Gas(coinObjId).GasBudget(1000000000)

txn, err := builder.Finish()
if err.(*sdk.SdkFfiError) != nil {
Expand All @@ -44,14 +43,13 @@ func main() {
log.Printf("Signing Digest: %v", sdk.HexEncode(txn.SigningDigest()))
log.Printf("Txn Bytes: %v", sdk.Base64Encode(txnBytes))

res, err := builder.DryRun(false)
skipChecks := bool(false)
res, err := client.DryRunTx(txn, &skipChecks)
if err.(*sdk.SdkFfiError) != nil {
log.Fatalf("Failed to split coins: %v", err)
log.Fatalf("Failed to dry run split coins: %v", err)
}

if res.Error != nil {
log.Fatalf("Failed to split coins: %v", *res.Error)
}

log.Print("Split coins dry run was successful!")
}
6 changes: 6 additions & 0 deletions bindings/go/iota_sdk_ffi/iota_sdk_ffi.go
Original file line number Diff line number Diff line change
Expand Up @@ -25290,13 +25290,17 @@ type ChangedObject struct {
// This information isn't required by the protocol but is useful for
// providing more detailed semantics on object changes.
IdOperation IdOperation
// Optional object type information. This is not part of the BCS protocol
// data but can be populated from other sources when available.
ObjectType *string
}

func (r *ChangedObject) Destroy() {
FfiDestroyerObjectId{}.Destroy(r.ObjectId);
FfiDestroyerObjectIn{}.Destroy(r.InputState);
FfiDestroyerObjectOut{}.Destroy(r.OutputState);
FfiDestroyerIdOperation{}.Destroy(r.IdOperation);
FfiDestroyerOptionalString{}.Destroy(r.ObjectType);
}

type FfiConverterChangedObject struct {}
Expand All @@ -25313,6 +25317,7 @@ func (c FfiConverterChangedObject) Read(reader io.Reader) ChangedObject {
FfiConverterObjectInINSTANCE.Read(reader),
FfiConverterObjectOutINSTANCE.Read(reader),
FfiConverterIdOperationINSTANCE.Read(reader),
FfiConverterOptionalStringINSTANCE.Read(reader),
}
}

Expand All @@ -25325,6 +25330,7 @@ func (c FfiConverterChangedObject) Write(writer io.Writer, value ChangedObject)
FfiConverterObjectInINSTANCE.Write(writer, value.InputState);
FfiConverterObjectOutINSTANCE.Write(writer, value.OutputState);
FfiConverterIdOperationINSTANCE.Write(writer, value.IdOperation);
FfiConverterOptionalStringINSTANCE.Write(writer, value.ObjectType);
}

type FfiDestroyerChangedObject struct {}
Expand Down
15 changes: 12 additions & 3 deletions bindings/kotlin/lib/iota_sdk/iota_sdk_ffi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45255,7 +45255,12 @@ data class ChangedObject (
* This information isn't required by the protocol but is useful for
* providing more detailed semantics on object changes.
*/
var `idOperation`: IdOperation
var `idOperation`: IdOperation,
/**
* Optional object type information. This is not part of the BCS protocol
* data but can be populated from other sources when available.
*/
var `objectType`: kotlin.String? = null
) : Disposable {

@Suppress("UNNECESSARY_SAFE_CALL") // codegen is much simpler if we unconditionally emit safe calls here
Expand All @@ -45265,7 +45270,8 @@ data class ChangedObject (
this.`objectId`,
this.`inputState`,
this.`outputState`,
this.`idOperation`
this.`idOperation`,
this.`objectType`
)
}

Expand All @@ -45282,21 +45288,24 @@ public object FfiConverterTypeChangedObject: FfiConverterRustBuffer<ChangedObjec
FfiConverterTypeObjectIn.read(buf),
FfiConverterTypeObjectOut.read(buf),
FfiConverterTypeIdOperation.read(buf),
FfiConverterOptionalString.read(buf),
)
}

override fun allocationSize(value: ChangedObject) = (
FfiConverterTypeObjectId.allocationSize(value.`objectId`) +
FfiConverterTypeObjectIn.allocationSize(value.`inputState`) +
FfiConverterTypeObjectOut.allocationSize(value.`outputState`) +
FfiConverterTypeIdOperation.allocationSize(value.`idOperation`)
FfiConverterTypeIdOperation.allocationSize(value.`idOperation`) +
FfiConverterOptionalString.allocationSize(value.`objectType`)
)

override fun write(value: ChangedObject, buf: ByteBuffer) {
FfiConverterTypeObjectId.write(value.`objectId`, buf)
FfiConverterTypeObjectIn.write(value.`inputState`, buf)
FfiConverterTypeObjectOut.write(value.`outputState`, buf)
FfiConverterTypeIdOperation.write(value.`idOperation`, buf)
FfiConverterOptionalString.write(value.`objectType`, buf)
}
}

Expand Down
Loading