Skip to content

Commit b3b84a7

Browse files
committed
wip
1 parent 42a388d commit b3b84a7

File tree

11 files changed

+2304
-138
lines changed

11 files changed

+2304
-138
lines changed

clients/bindings.go

Lines changed: 127 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"math"
88
"math/big"
99
"reflect"
10+
"regexp"
1011
"strconv"
1112
"strings"
1213
"time"
@@ -21,7 +22,6 @@ import (
2122
"github.com/iotaledger/wasp/v2/clients/iota-go/iotago/serialization"
2223
"github.com/iotaledger/wasp/v2/clients/iota-go/iotajsonrpc"
2324
"github.com/iotaledger/wasp/v2/clients/iota-go/iotasigner"
24-
"github.com/iotaledger/wasp/v2/clients/iscmove/iscmoveclient"
2525
"github.com/iotaledger/wasp/v2/packages/cryptolib"
2626
)
2727

@@ -49,7 +49,7 @@ func NewBindingClient(rpcUrl string) *BindingClient {
4949

5050
switch rpcUrl {
5151
case iotaconn.LocalnetEndpointURL:
52-
client.qclient = iota_sdk_ffi.GraphQlClientNewLocalhost()
52+
client.qclient = iota_sdk_ffi.GraphQlClientNewLocalnet()
5353
case iotaconn.TestnetEndpointURL:
5454
client.qclient = iota_sdk_ffi.GraphQlClientNewTestnet()
5555
case iotaconn.DevnetEndpointURL:
@@ -222,7 +222,7 @@ func toFfiTypeTag(tag *iotago.TypeTag) (*iota_sdk_ffi.TypeTag, error) {
222222
return nil, fmt.Errorf("unknown TypeTag variant")
223223
}
224224

225-
func mapFfiObjectToIotaResponse(obj **iota_sdk_ffi.Object) (*iotajsonrpc.IotaObjectResponse, error) {
225+
func mapFfiObjectToIotaResponse(obj **iota_sdk_ffi.Object, options *iotajsonrpc.IotaObjectDataOptions, bcsBytes *[]byte) (*iotajsonrpc.IotaObjectResponse, error) {
226226
if obj == nil || *obj == nil {
227227
return &iotajsonrpc.IotaObjectResponse{}, nil
228228
}
@@ -238,7 +238,8 @@ func mapFfiObjectToIotaResponse(obj **iota_sdk_ffi.Object) (*iotajsonrpc.IotaObj
238238
return nil, err
239239
}
240240
var typeStr *string
241-
if ot := o.ObjectType(); ot != nil {
241+
ot := o.ObjectType()
242+
if ot != nil {
242243
s := ot.String()
243244
typeStr = &s
244245
}
@@ -255,9 +256,81 @@ func mapFfiObjectToIotaResponse(obj **iota_sdk_ffi.Object) (*iotajsonrpc.IotaObj
255256
PreviousTransaction: prev,
256257
StorageRebate: iotajsonrpc.NewBigInt(o.StorageRebate()),
257258
}
259+
260+
// Add owner if requested
261+
if options != nil && options.ShowOwner {
262+
if owner := o.Owner(); owner != nil {
263+
iotaOwner, err := fromFfiOwner(owner)
264+
if err != nil {
265+
return nil, fmt.Errorf("failed to convert owner: %w", err)
266+
}
267+
if iotaOwner != nil {
268+
ownerInternal := &iotajsonrpc.ObjectOwnerInternal{
269+
AddressOwner: iotaOwner.AddressOwner,
270+
ObjectOwner: iotaOwner.ObjectOwner,
271+
}
272+
// Convert Shared field if present
273+
if iotaOwner.Shared != nil {
274+
ownerInternal.Shared = &struct {
275+
InitialSharedVersion *iotago.SequenceNumber `json:"initial_shared_version"`
276+
}{
277+
InitialSharedVersion: &iotaOwner.Shared.InitialSharedVersion,
278+
}
279+
}
280+
data.Owner = &iotajsonrpc.ObjectOwner{
281+
ObjectOwnerInternal: ownerInternal,
282+
}
283+
}
284+
}
285+
}
286+
287+
// Add BCS data if requested and available
288+
if options != nil && options.ShowBcs && bcsBytes != nil && *bcsBytes != nil {
289+
bcsData := iotago.Base64Data(*bcsBytes)
290+
291+
// For move objects, we need to populate the IotaRawMoveObject structure
292+
if typeStr != nil {
293+
structTag, err := iotago.StructTagFromString(extractTypeTag(*typeStr))
294+
if err == nil {
295+
data.Bcs = &serialization.TagJson[iotajsonrpc.IotaRawData]{
296+
Data: iotajsonrpc.IotaRawData{
297+
MoveObject: &iotajsonrpc.IotaRawMoveObject{
298+
Type: *structTag,
299+
HasPublicTransfer: false, // This would need to be determined from object data
300+
Version: iotago.SequenceNumber(ver),
301+
BcsBytes: bcsData,
302+
},
303+
},
304+
}
305+
}
306+
}
307+
}
308+
258309
return &iotajsonrpc.IotaObjectResponse{Data: data}, nil
259310
}
260311

312+
var moveTagRe = regexp.MustCompile(
313+
`^(?:Struct\()?(0x[0-9a-fA-F]+::[A-Za-z_][A-Za-z0-9_]*::[A-Za-z_][A-Za-z0-9_]*)(?:\))?$`,
314+
)
315+
316+
func extractTypeTag(s string) string {
317+
s = strings.TrimSpace(s)
318+
if m := moveTagRe.FindStringSubmatch(s); m != nil {
319+
return m[1]
320+
}
321+
// Fallback: if parentheses exist, peel the first (...) pair.
322+
if l := strings.IndexByte(s, '('); l >= 0 {
323+
if r := strings.IndexByte(s[l+1:], ')'); r >= 0 {
324+
return s[l+1 : l+1+r]
325+
}
326+
}
327+
// Otherwise just return as-is if non-empty.
328+
if s != "" {
329+
return s
330+
}
331+
return ""
332+
}
333+
261334
// formatExecutionError formats an ExecutionError with type information
262335
func formatExecutionError(err iota_sdk_ffi.ExecutionError) string {
263336
switch e := err.(type) {
@@ -566,7 +639,8 @@ func populateObjectTypesFromDryRun(effects *iota_sdk_ffi.TransactionEffects, dry
566639
}
567640

568641
// convertChangedObjectsToObjectChanges converts FFI TransactionEffects ChangedObjects to ObjectChanges
569-
func convertChangedObjectsToObjectChanges(effects *iota_sdk_ffi.TransactionEffects) ([]serialization.TagJson[iotajsonrpc.ObjectChange], error) {
642+
func (c *BindingClient) convertChangedObjectsToObjectChanges(effects *iota_sdk_ffi.TransactionEffects) ([]serialization.TagJson[iotajsonrpc.ObjectChange], error) {
643+
time.Sleep(400 * time.Millisecond)
570644
if effects == nil {
571645
return nil, nil
572646
}
@@ -582,17 +656,17 @@ func convertChangedObjectsToObjectChanges(effects *iota_sdk_ffi.TransactionEffec
582656
// We'll create a zero address as a placeholder.
583657
zeroAddr := iotago.Address{}
584658
for _, changedObj := range v1.ChangedObjects {
659+
fmt.Println("*******changedObj.IdOperation: ", changedObj.IdOperation)
660+
fmt.Println("*******changedObj.ObjectType: ", changedObj.ObjectType)
661+
fmt.Println("*******changedObj.ObjectId: ", changedObj.ObjectId.ToHex())
662+
if changedObj.ObjectType != nil {
663+
fmt.Println("*******!changedObj: ", *changedObj.ObjectType)
664+
}
585665
objID, err := fromFfiObjectID(changedObj.ObjectId)
586666
if err != nil || objID == nil {
587667
continue
588668
}
589669

590-
// Extract object type if available
591-
objectType := ""
592-
if changedObj.ObjectType != nil {
593-
objectType = *changedObj.ObjectType
594-
}
595-
596670
// Determine object state changes
597671
inputIsMissing := false
598672
outputIsMissing := false
@@ -630,6 +704,10 @@ func convertChangedObjectsToObjectChanges(effects *iota_sdk_ffi.TransactionEffec
630704

631705
// Create ObjectChange based on state transitions
632706
var change iotajsonrpc.ObjectChange
707+
var changeObjectType string
708+
if changedObj.ObjectType != nil {
709+
changeObjectType = *changedObj.ObjectType
710+
}
633711

634712
switch changedObj.IdOperation {
635713
case iota_sdk_ffi.IdOperationCreated:
@@ -647,6 +725,19 @@ func convertChangedObjectsToObjectChanges(effects *iota_sdk_ffi.TransactionEffec
647725
Nodules: []string{}, // TODO: Extract module names if available
648726
}
649727
} else if !outputIsMissing && outputDigest != nil && outputOwner != nil {
728+
resGetObject, err := c.GetObject(context.TODO(), iotaclient.GetObjectRequest{ObjectID: objID, Options: &iotajsonrpc.IotaObjectDataOptions{
729+
ShowType: true,
730+
ShowContent: true,
731+
ShowBcs: true,
732+
ShowOwner: true,
733+
ShowPreviousTransaction: true,
734+
ShowStorageRebate: true,
735+
ShowDisplay: true,
736+
}})
737+
if err != nil {
738+
panic(err)
739+
}
740+
650741
change.Created = &struct {
651742
Sender iotago.Address `json:"sender"`
652743
Owner iotajsonrpc.ObjectOwner `json:"owner"`
@@ -657,7 +748,7 @@ func convertChangedObjectsToObjectChanges(effects *iota_sdk_ffi.TransactionEffec
657748
}{
658749
Sender: zeroAddr,
659750
Owner: iotagoOwnerToObjectOwner(outputOwner),
660-
ObjectType: objectType,
751+
ObjectType: *resGetObject.Data.Type,
661752
ObjectID: *objID,
662753
Version: iotajsonrpc.NewBigInt(v1.LamportVersion),
663754
Digest: *outputDigest,
@@ -675,7 +766,7 @@ func convertChangedObjectsToObjectChanges(effects *iota_sdk_ffi.TransactionEffec
675766
Version *iotajsonrpc.BigInt `json:"version"`
676767
}{
677768
Sender: zeroAddr,
678-
ObjectType: objectType,
769+
ObjectType: changeObjectType,
679770
ObjectID: *objID,
680771
Version: iotajsonrpc.NewBigInt(v1.LamportVersion),
681772
}
@@ -689,7 +780,7 @@ func convertChangedObjectsToObjectChanges(effects *iota_sdk_ffi.TransactionEffec
689780
Version *iotajsonrpc.BigInt `json:"version"`
690781
}{
691782
Sender: zeroAddr,
692-
ObjectType: objectType,
783+
ObjectType: changeObjectType,
693784
ObjectID: *objID,
694785
Version: iotajsonrpc.NewBigInt(v1.LamportVersion),
695786
}
@@ -705,7 +796,7 @@ func convertChangedObjectsToObjectChanges(effects *iota_sdk_ffi.TransactionEffec
705796
}{
706797
Sender: zeroAddr,
707798
Owner: iotagoOwnerToObjectOwner(outputOwner),
708-
ObjectType: objectType,
799+
ObjectType: changeObjectType,
709800
ObjectID: *objID,
710801
Version: iotajsonrpc.NewBigInt(v1.LamportVersion),
711802
PreviousVersion: iotajsonrpc.NewBigInt(v1.LamportVersion - 1), // Approximation
@@ -789,7 +880,7 @@ func (c *BindingClient) GetOwnedObjects(ctx context.Context, req iotaclient.GetO
789880
if err.(*iota_sdk_ffi.SdkFfiError) != nil {
790881
return nil, fmt.Errorf("Object failed: %w", err)
791882
}
792-
resp, err := mapFfiObjectToIotaResponse(obj)
883+
resp, err := mapFfiObjectToIotaResponse(obj, nil, nil)
793884
if err != nil {
794885
return nil, err
795886
}
@@ -941,7 +1032,7 @@ func (c *BindingClient) DryRunTransaction(ctx context.Context, txDataBytes iotag
9411032
response.Effects = serialization.TagJson[iotajsonrpc.IotaTransactionBlockEffects]{Data: *convertedEffects}
9421033

9431034
// Convert object changes
944-
objectChanges, err := convertChangedObjectsToObjectChanges(*dryRunResult.Effects)
1035+
objectChanges, err := c.convertChangedObjectsToObjectChanges(*dryRunResult.Effects)
9451036
if err != nil {
9461037
return nil, fmt.Errorf("failed to convert object changes: %w", err)
9471038
}
@@ -2705,7 +2796,7 @@ func (c *BindingClient) SignAndExecuteTransaction(ctx context.Context, req *iota
27052796
response.Effects = &serialization.TagJson[iotajsonrpc.IotaTransactionBlockEffects]{Data: *convertedEffects}
27062797
}
27072798
if req.Options.ShowObjectChanges {
2708-
objectChanges, err := convertChangedObjectsToObjectChanges(*txEffects)
2799+
objectChanges, err := c.convertChangedObjectsToObjectChanges(*txEffects)
27092800
if err != nil {
27102801
return nil, fmt.Errorf("failed to convert object changes: %w", err)
27112802
}
@@ -3011,7 +3102,7 @@ func (c *BindingClient) BatchGetObjectsOwnedByAddress(ctx context.Context, addre
30113102

30123103
var results []iotajsonrpc.IotaObjectResponse
30133104
for _, obj := range objectPage.Data {
3014-
resp, err := mapFfiObjectToIotaResponse(&obj)
3105+
resp, err := mapFfiObjectToIotaResponse(&obj, options, nil)
30153106
if err != nil {
30163107
return nil, fmt.Errorf("failed to map object: %w", err)
30173108
}
@@ -3340,12 +3431,25 @@ func (c *BindingClient) GetObject(ctx context.Context, req iotaclient.GetObjectR
33403431
if err != nil {
33413432
return nil, err
33423433
}
3434+
33433435
obj, err := c.qclient.Object(oid, nil)
33443436
if err.(*iota_sdk_ffi.SdkFfiError) != nil {
33453437
return nil, fmt.Errorf("GraphQL Object failed: %w", err)
33463438
}
33473439

3348-
return mapFfiObjectToIotaResponse(obj)
3440+
// Fetch BCS data if requested
3441+
var bcsBytes *[]byte
3442+
if req.Options != nil && req.Options.ShowBcs {
3443+
// Use MoveObjectContentsBcs to get just the Move object contents (not the full object wrapper)
3444+
// This matches what the JSON-RPC API returns for showBcs and allows direct deserialization
3445+
bcs, err := c.qclient.MoveObjectContentsBcs(oid, nil)
3446+
if err.(*iota_sdk_ffi.SdkFfiError) == nil && bcs != nil {
3447+
bcsBytes = bcs
3448+
}
3449+
// Silently ignore BCS fetch errors - BCS data might not be available for all objects
3450+
}
3451+
3452+
return mapFfiObjectToIotaResponse(obj, req.Options, bcsBytes)
33493453
}
33503454

33513455
func (c *BindingClient) GetProtocolConfig(ctx context.Context, version *iotajsonrpc.BigInt) (*iotajsonrpc.ProtocolConfig, error) {
@@ -3495,7 +3599,7 @@ func (c *BindingClient) MultiGetObjects(ctx context.Context, req iotaclient.Mult
34953599

34963600
var results []iotajsonrpc.IotaObjectResponse
34973601
for _, obj := range objectPage.Data {
3498-
resp, err := mapFfiObjectToIotaResponse(&obj)
3602+
resp, err := mapFfiObjectToIotaResponse(&obj, req.Options, nil)
34993603
if err != nil {
35003604
return nil, fmt.Errorf("failed to map object: %w", err)
35013605
}
@@ -3574,8 +3678,7 @@ func (c *BindingClient) Health(ctx context.Context) error {
35743678
}
35753679

35763680
func (c *BindingClient) L2() L2Client {
3577-
faucetURL := iotaconn.FaucetURL(c.RpcURL)
3578-
return iscmoveclient.NewClient(c.RpcURL, faucetURL)
3681+
return NewBindingClientL2(c.RpcURL, c)
35793682
}
35803683

35813684
func (c *BindingClient) IotaClient() L1Client {
@@ -3867,7 +3970,7 @@ func (c *BindingClient) buildTransactionAndExecute(_ context.Context, signer iot
38673970
response.Effects = &serialization.TagJson[iotajsonrpc.IotaTransactionBlockEffects]{Data: *convertedEffects}
38683971
}
38693972
if options.ShowObjectChanges {
3870-
objectChanges, err := convertChangedObjectsToObjectChanges(*txEffects)
3973+
objectChanges, err := c.convertChangedObjectsToObjectChanges(*txEffects)
38713974
if err != nil {
38723975
return nil, fmt.Errorf("failed to convert object changes: %w", err)
38733976
}

clients/bindings/bind.sh

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@ set -euo pipefail
44
root_path=$(git rev-parse --show-toplevel)
55

66
# use commit b921ab3e65acbe377cd4da0ec6d8421fecc15ad8
7-
git clone --depth=1 --branch sdk-bindings --single-branch https://github.com/iotaledger/iota-rust-sdk.git "$root_path/clients/bindings/iota-rust-sdk" || true
7+
# git clone --branch modify-sdk --single-branch git@github.com:howjmay/iota-rust-sdk.git "$root_path/clients/bindings/iota-rust-sdk" || true
8+
# cd $root_path/clients/bindings/iota-rust-sdk
9+
# git switch --detach b921ab3e65acbe377cd4da0ec6d8421fecc15ad8
10+
# cd ..
811

912
iota_binding_dir="$root_path/clients/bindings"
1013
iota_go_ffi_dir="$iota_binding_dir/iota_sdk_ffi"
1114
iota_go_ffi_file="$iota_go_ffi_dir/iota_sdk_ffi.go"
1215

1316
iota_rust_sdk_path="$iota_binding_dir/iota-rust-sdk"
14-
go_ffi_dir="$iota_rust_sdk_path/bindings/go/iota_sdk_ffi/iota_sdk_ffi"
15-
go_ffi_file="$go_ffi_dir/iota_sdk_ffi.go"
16-
17-
go_ffi_target_dir="$root_path/clients/bindings/iota-rust-sdk/target"
17+
iota_rust_go_ffi_dir="$iota_rust_sdk_path/bindings/go/iota_sdk_ffi"
1818

1919
cd "$iota_rust_sdk_path"
2020
cargo build --all-features -p iota-sdk-ffi --lib --release
@@ -28,20 +28,20 @@ case "$(uname -s)" in
2828
esac
2929
lib_path="${lib_base}.${ext}"
3030

31-
command -v uniffi-bindgen-go >/dev/null || {
32-
echo "uniffi-bindgen-go not found in PATH" >&2
33-
exit 1
34-
}
3531
[[ -f "$lib_path" ]] || {
3632
echo "Library not found: $lib_path" >&2
3733
exit 1
3834
}
3935

40-
# Clean up old generated files before generating new ones
41-
rm -rf "$root_path/clients/bindings/iota_sdk_ffi"
42-
43-
uniffi-bindgen-go --library "$lib_path" --out-dir "$iota_binding_dir" --no-format
44-
echo "Generated Go bindings to $iota_binding_dir using $lib_path"
36+
# Overwrite local Go FFI bindings with those from iota-rust-sdk
37+
rm -rf "$iota_go_ffi_dir"
38+
if [[ -d "$iota_rust_go_ffi_dir" ]]; then
39+
cp -R "$iota_rust_go_ffi_dir" "$iota_binding_dir/"
40+
echo "Copied Go bindings from $iota_rust_go_ffi_dir to $iota_binding_dir"
41+
else
42+
echo "Source bindings not found: $iota_rust_go_ffi_dir" >&2
43+
exit 1
44+
fi
4545

4646
if [[ -f "$iota_go_ffi_file" ]]; then
4747
# Only replace if the placeholder include line exists
@@ -59,9 +59,3 @@ else
5959
echo "File not found: $iota_go_ffi_file" >&2
6060
exit 1
6161
fi
62-
63-
64-
# cp -R $go_ffi_target_dir $root_path/clients/bindings/iota_sdk_ffi
65-
66-
67-

0 commit comments

Comments
 (0)