Skip to content
Merged
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
121 changes: 121 additions & 0 deletions bindings/go/examples/stake.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// Copyright (c) 2025 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

package main

import (
"log"

sdk "bindings/iota_sdk_ffi"
)

func isNilError(err error) bool {
if sdkErr, ok := err.(*sdk.SdkFfiError); ok {
return sdkErr == nil
}
return false
}

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

myAddress, err := sdk.AddressFromHex("0x611830d3641a68f94a690dcc25d1f4b0dac948325ac18f6dd32564371735f32c")
if err != nil {
log.Fatalf("Failed to parse address: %v", err)
}

validators, err := client.ActiveValidators(nil, &sdk.PaginationFilter{Direction: sdk.DirectionForward})
if !isNilError(err) {
log.Fatalf("Failed to get active validators: %v", err)
}

if len(validators.Data) == 0 {
log.Fatal("No validators found")
}
validator := validators.Data[0]

var validatorName string
if validator.Name == nil {
validatorName = "with no name"
} else {
validatorName = *validator.Name
}
log.Printf("Staking to validator %v", validatorName)

coinObjId, err := sdk.ObjectIdFromHex("0xd04077fe3b6fad13b3d4ed0d535b7ca92afcac8f0f2a0e0925fb9f4f0b30c699")
if err != nil {
log.Fatalf("Failed to parse object ID: %v", err)
}
coin, err := client.Object(coinObjId, nil)
if !isNilError(err) {
log.Fatalf("Failed to get coin: %v", err)
}

gasCoinObjId, err := sdk.ObjectIdFromHex("0x0b0270ee9d27da0db09651e5f7338dfa32c7ee6441ccefa1f6e305735bcfc7ab")
if err != nil {
log.Fatalf("Failed to parse object ID: %v", err)
}
gasCoin, err := client.Object(gasCoinObjId, nil)
if !isNilError(err) {
log.Fatalf("Failed to get gas coin: %v", err)
}

iotaSystemAddress, err := sdk.AddressFromHex("0x3")
if err != nil {
log.Fatalf("Failed to parse address: %v", err)
}

iotaSystemId, err := sdk.ObjectIdFromHex("0x5")
if err != nil {
log.Fatalf("Failed to parse object ID: %v", err)
}

iotaSystemModule, err := sdk.NewIdentifier("iota_system")
if err != nil {
log.Fatalf("Failed to parse identifier: %v", err)
}

requestAddStakeFn, err := sdk.NewIdentifier("request_add_stake")
if err != nil {
log.Fatalf("Failed to parse identifier: %v", err)
}

builder := sdk.NewTransactionBuilder()
inputs := []*sdk.Argument{
builder.Input(sdk.UnresolvedInputNewShared(iotaSystemId, 1, true)),
builder.Input(sdk.UnresolvedInputFromObject(*coin).WithOwnedKind()),
builder.Input(sdk.UnresolvedInputNewPure(validator.Address.ToBytes())),
}
builder.MoveCall(
sdk.Function{
Package: iotaSystemAddress,
Module: iotaSystemModule,
Function: requestAddStakeFn,
},
inputs,
)
builder.SetSender(myAddress)
builder.SetGasBudget(50000000)
gasPrice, err := client.ReferenceGasPrice(nil)
if !isNilError(err) {
log.Fatalf("Failed to get gas price: %v", err)
}
builder.SetGasPrice(*gasPrice)
builder.AddGasObjects([]*sdk.UnresolvedInput{sdk.UnresolvedInputFromObject(*gasCoin).WithOwnedKind()})

txn, err := builder.Finish()
if err != nil {
log.Fatalf("Failed to create transaction: %v", err)
}

res, err := client.DryRunTx(txn, nil)
if !isNilError(err) {
log.Fatalf("Failed to get gas price: %v", err)
}

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

log.Print("Stake dry run was successful!")
}
100 changes: 100 additions & 0 deletions bindings/go/examples/unstake.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright (c) 2025 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

package main

import (
"log"

sdk "bindings/iota_sdk_ffi"
)

func isNilError(err error) bool {
if sdkErr, ok := err.(*sdk.SdkFfiError); ok {
return sdkErr == nil
}
return false
}

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

stakedIotaType := "0x3::staking_pool::StakedIota"
stakedIotas, err := client.Objects(&sdk.ObjectFilter{TypeTag: &stakedIotaType}, nil)
if !isNilError(err) {
log.Fatalf("Failed to get staked iota: %v", err)
}
if len(stakedIotas.Data) == 0 {
log.Fatal("No staked iota objects found")
}
stakedIota := stakedIotas.Data[0]

gasCoinType := sdk.StructTagGasCoin().String()
gasCoins, err := client.Objects(&sdk.ObjectFilter{TypeTag: &gasCoinType, Owner: stakedIota.Owner().AsAddressOpt()}, nil)
if !isNilError(err) {
log.Fatalf("Failed to get gas coin: %v", err)
}
if len(gasCoins.Data) == 0 {
log.Fatal("No gas coins found")
}
gasCoin := gasCoins.Data[0]

iotaSystemAddress, err := sdk.AddressFromHex("0x3")
if err != nil {
log.Fatalf("Failed to parse address: %v", err)
}

iotaSystemId, err := sdk.ObjectIdFromHex("0x5")
if err != nil {
log.Fatalf("Failed to parse object ID: %v", err)
}

iotaSystemModule, err := sdk.NewIdentifier("iota_system")
if err != nil {
log.Fatalf("Failed to parse identifier: %v", err)
}

requestAddStakeFn, err := sdk.NewIdentifier("request_withdraw_stake")
if err != nil {
log.Fatalf("Failed to parse identifier: %v", err)
}

builder := sdk.NewTransactionBuilder()
inputs := []*sdk.Argument{
builder.Input(sdk.UnresolvedInputNewShared(iotaSystemId, 1, true)),
builder.Input(sdk.UnresolvedInputFromObject(stakedIota).WithOwnedKind()),
}
builder.MoveCall(
sdk.Function{
Package: iotaSystemAddress,
Module: iotaSystemModule,
Function: requestAddStakeFn,
TypeArgs: []*sdk.TypeTag{},
},
inputs,
)
builder.SetSender(gasCoin.Owner().AsAddress())
builder.SetGasBudget(50000000)
gasPrice, err := client.ReferenceGasPrice(nil)
if !isNilError(err) {
log.Fatalf("Failed to get gas price: %v", err)
}
builder.SetGasPrice(*gasPrice)
builder.AddGasObjects([]*sdk.UnresolvedInput{sdk.UnresolvedInputFromObject(gasCoin).WithOwnedKind()})

txn, err := builder.Finish()
if err != nil {
log.Fatalf("Failed to create transaction: %v", err)
}

res, err := client.DryRunTx(txn, nil)
if !isNilError(err) {
log.Fatalf("Failed to get gas price: %v", err)
}

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

log.Print("Unstake dry run was successful!")
}
15 changes: 15 additions & 0 deletions bindings/go/iota_sdk_ffi/iota_sdk_ffi.go
Original file line number Diff line number Diff line change
Expand Up @@ -5867,6 +5867,15 @@ func uniffiCheckChecksums() {
}
}
{
checksum := rustCall(func(_uniffiStatus *C.RustCallStatus) C.uint16_t {
return C.uniffi_iota_sdk_ffi_checksum_constructor_unresolvedinput_new_pure()
})
if checksum != 7951 {
// If this happens try cleaning and rebuilding your project
panic("iota_sdk_ffi: uniffi_iota_sdk_ffi_checksum_constructor_unresolvedinput_new_pure: UniFFI API checksum mismatch")
}
}
{
checksum := rustCall(func(_uniffiStatus *C.RustCallStatus) C.uint16_t {
return C.uniffi_iota_sdk_ffi_checksum_constructor_unresolvedinput_new_receiving()
})
Expand Down Expand Up @@ -20862,6 +20871,12 @@ func UnresolvedInputNewOwned(objectId *ObjectId, version uint64, digest *Digest)
}))
}

func UnresolvedInputNewPure(bytes []byte) *UnresolvedInput {
return FfiConverterUnresolvedInputINSTANCE.Lift(rustCall(func(_uniffiStatus *C.RustCallStatus) unsafe.Pointer {
return C.uniffi_iota_sdk_ffi_fn_constructor_unresolvedinput_new_pure(FfiConverterBytesINSTANCE.Lower(bytes),_uniffiStatus)
}))
}

// Return a receiving kind of object with all required fields.
func UnresolvedInputNewReceiving(objectId *ObjectId, version uint64, digest *Digest) *UnresolvedInput {
return FfiConverterUnresolvedInputINSTANCE.Lift(rustCall(func(_uniffiStatus *C.RustCallStatus) unsafe.Pointer {
Expand Down
11 changes: 11 additions & 0 deletions bindings/go/iota_sdk_ffi/iota_sdk_ffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -4021,6 +4021,11 @@ void* uniffi_iota_sdk_ffi_fn_constructor_unresolvedinput_new_immutable(void* obj
void* uniffi_iota_sdk_ffi_fn_constructor_unresolvedinput_new_owned(void* object_id, uint64_t version, void* digest, RustCallStatus *out_status
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IOTA_SDK_FFI_FN_CONSTRUCTOR_UNRESOLVEDINPUT_NEW_PURE
#define UNIFFI_FFIDEF_UNIFFI_IOTA_SDK_FFI_FN_CONSTRUCTOR_UNRESOLVEDINPUT_NEW_PURE
void* uniffi_iota_sdk_ffi_fn_constructor_unresolvedinput_new_pure(RustBuffer bytes, RustCallStatus *out_status
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IOTA_SDK_FFI_FN_CONSTRUCTOR_UNRESOLVEDINPUT_NEW_RECEIVING
#define UNIFFI_FFIDEF_UNIFFI_IOTA_SDK_FFI_FN_CONSTRUCTOR_UNRESOLVEDINPUT_NEW_RECEIVING
void* uniffi_iota_sdk_ffi_fn_constructor_unresolvedinput_new_receiving(void* object_id, uint64_t version, void* digest, RustCallStatus *out_status
Expand Down Expand Up @@ -8574,6 +8579,12 @@ uint16_t uniffi_iota_sdk_ffi_checksum_constructor_unresolvedinput_new_immutable(
#define UNIFFI_FFIDEF_UNIFFI_IOTA_SDK_FFI_CHECKSUM_CONSTRUCTOR_UNRESOLVEDINPUT_NEW_OWNED
uint16_t uniffi_iota_sdk_ffi_checksum_constructor_unresolvedinput_new_owned(void

);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IOTA_SDK_FFI_CHECKSUM_CONSTRUCTOR_UNRESOLVEDINPUT_NEW_PURE
#define UNIFFI_FFIDEF_UNIFFI_IOTA_SDK_FFI_CHECKSUM_CONSTRUCTOR_UNRESOLVEDINPUT_NEW_PURE
uint16_t uniffi_iota_sdk_ffi_checksum_constructor_unresolvedinput_new_pure(void

);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IOTA_SDK_FFI_CHECKSUM_CONSTRUCTOR_UNRESOLVEDINPUT_NEW_RECEIVING
Expand Down
87 changes: 87 additions & 0 deletions bindings/kotlin/examples/Stake.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright (c) 2025 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

import iota_sdk.Address
import iota_sdk.Direction
import iota_sdk.Function
import iota_sdk.GraphQlClient
import iota_sdk.Identifier
import iota_sdk.ObjectId
import iota_sdk.PaginationFilter
import iota_sdk.TransactionBuilder
import iota_sdk.UnresolvedInput
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
try {
val client = GraphQlClient.newDevnet()

val myAddress =
Address.fromHex(
"0x611830d3641a68f94a690dcc25d1f4b0dac948325ac18f6dd32564371735f32c"
)

val validators = client.activeValidators(null, PaginationFilter(Direction.FORWARD))
if (validators.data.isEmpty()) {
throw Exception("no validators found")
}
val validator = validators.data[0]

println("Staking to validator ${validator.name ?: "with no name"}")

val coin =
client.`object`(
ObjectId.fromHex(
"0xd04077fe3b6fad13b3d4ed0d535b7ca92afcac8f0f2a0e0925fb9f4f0b30c699"
)
)
if (coin == null) {
throw Exception("missing coin")
}

val gasCoin =
client.`object`(
ObjectId.fromHex(
"0x0b0270ee9d27da0db09651e5f7338dfa32c7ee6441ccefa1f6e305735bcfc7ab"
)
)
if (gasCoin == null) {
throw Exception("missing gas coin")
}

val builder = TransactionBuilder()
val inputs =
listOf(
builder.input(UnresolvedInput.newShared(ObjectId.fromHex("0x5"), 1u, true)),
builder.input(UnresolvedInput.fromObject(coin).withOwnedKind()),
builder.input(UnresolvedInput.newPure(validator.address.toBytes())),
)
builder.moveCall(
Function(
Address.fromHex("0x3"),
Identifier("iota_system"),
Identifier("request_add_stake"),
),
inputs
)
builder.setSender(myAddress)
builder.setGasBudget(50000000u)
val refGasPrice = client.referenceGasPrice(null)
if (refGasPrice == null) {
throw Exception("missing ref gas price")
}
builder.setGasPrice(refGasPrice)
builder.addGasObjects(listOf(UnresolvedInput.fromObject(gasCoin).withOwnedKind()))

val txn = builder.finish()
val res = client.dryRunTx(txn, false)

if (res.error != null) {
throw Exception(res.error)
}

println("Stake dry run was successful!")
} catch (e: Exception) {
e.printStackTrace()
}
}
Loading