Skip to content

Commit b921ab3

Browse files
feat: Add new transaction builder (#206)
* Add new transaction builder * remove unnecessary methods * improvements * examples * simplify * Update bindings * fmt and clippy * update years * improved input and gas handling * fix doc * fix test * rename new fn * fix gas ownership check * Remove CustomMoveType and fix some issues * clippy * reorganize builder files * make `Res` a fn * Split out name and arg fns * update examples * add command builder for more convenience * missed underflow * fix issues with dropping builder * revert examples * add method for adding multiple gas coins * wizardry * missed things * more improvements * cleanup * add `transfer_value` * doc and fix ordering * improve send_coins * add missing methods to ffi * update bindings * impl traits for more tuples * rename transfer_iota -> send_iota * safety and remove unused fn * impl PTBArguments for inputs * add effects back to dry run result * remove anyhow * fix mutable id * rename params -> arguments * clippy * rename fn * update bindings * flip a flag * another rename * review * typo * fix sdk crate * distinguish shared and shared mut * allow passing shared object IDs directly * rename named_comands * unsafe comments * more repr(C) * remove unnecessary Send bounds
1 parent 0b50800 commit b921ab3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+5677
-6213
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ Cargo.lock
55
*.so
66
*.dll
77
__pycache__
8+
build

bindings/go/examples/dev_inspect/main.go

Lines changed: 61 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -13,180 +13,97 @@ import (
1313
func main() {
1414
client := sdk.GraphQlClientNewDevnet()
1515

16-
senderAddress, err := sdk.AddressFromHex("0x0")
17-
if err != nil {
18-
log.Fatalf("Failed to parse sender address: %v", err)
19-
}
16+
sender, _ := sdk.AddressFromHex("0x0")
2017

21-
iotaNamesPackageAddress, err := sdk.AddressFromHex("0xb9d617f24c84826bf660a2f4031951678cc80c264aebc4413459fb2a95ada9ba")
22-
if err != nil {
23-
log.Fatalf("Failed to parse IOTA names package address: %v", err)
24-
}
18+
iotaNamesPackageAddress, _ := sdk.AddressFromHex("0xb9d617f24c84826bf660a2f4031951678cc80c264aebc4413459fb2a95ada9ba")
2519

26-
iotaNamesObjectId, err := sdk.ObjectIdFromHex("0x07c59b37bd7d036bf78fa30561a2ab9f7a970837487656ec29466e817f879342")
27-
if err != nil {
28-
log.Fatalf("Failed to parse IOTA names object ID: %v", err)
29-
}
20+
iotaNamesObjectId, _ := sdk.ObjectIdFromHex("0x07c59b37bd7d036bf78fa30561a2ab9f7a970837487656ec29466e817f879342")
3021

31-
stdlibAddress, err := sdk.AddressFromHex("0x1")
32-
if err != nil {
33-
log.Fatalf("Failed to parse stdlib address: %v", err)
34-
}
22+
stdlibAddress, _ := sdk.AddressFromHex("0x1")
3523

3624
name := "name.iota"
3725
fmt.Printf("Looking up name: %s\n", name)
3826

39-
builder := sdk.NewTransactionBuilder()
27+
builder := sdk.TransactionBuilderInit(sender, client)
4028

4129
// Create identifiers
42-
iotaNamesModule, err := sdk.NewIdentifier("iota_names")
43-
if err != nil {
44-
log.Fatalf("Failed to create identifier: %v", err)
45-
}
46-
registryFn, err := sdk.NewIdentifier("registry")
47-
if err != nil {
48-
log.Fatalf("Failed to create identifier: %v", err)
49-
}
50-
nameModule, err := sdk.NewIdentifier("name")
51-
if err != nil {
52-
log.Fatalf("Failed to create identifier: %v", err)
53-
}
54-
newFn, err := sdk.NewIdentifier("new")
55-
if err != nil {
56-
log.Fatalf("Failed to create identifier: %v", err)
57-
}
58-
lookupFn, err := sdk.NewIdentifier("lookup")
59-
if err != nil {
60-
log.Fatalf("Failed to create identifier: %v", err)
61-
}
62-
optionModule, err := sdk.NewIdentifier("option")
63-
if err != nil {
64-
log.Fatalf("Failed to create identifier: %v", err)
65-
}
66-
borrowFn, err := sdk.NewIdentifier("borrow")
67-
if err != nil {
68-
log.Fatalf("Failed to create identifier: %v", err)
69-
}
70-
nameRecordModule, err := sdk.NewIdentifier("name_record")
71-
if err != nil {
72-
log.Fatalf("Failed to create identifier: %v", err)
73-
}
74-
targetAddressFn, err := sdk.NewIdentifier("target_address")
75-
if err != nil {
76-
log.Fatalf("Failed to create identifier: %v", err)
77-
}
78-
79-
// Create type tags
80-
registryName, err := sdk.NewIdentifier("Registry")
81-
if err != nil {
82-
log.Fatalf("Failed to create identifier: %v", err)
83-
}
84-
registryType := sdk.NewStructTag(iotaNamesPackageAddress, registryFn, registryName, []*sdk.TypeTag{})
85-
86-
nameRecordName, err := sdk.NewIdentifier("NameRecord")
87-
if err != nil {
88-
log.Fatalf("Failed to create identifier: %v", err)
89-
}
30+
iotaNamesModule, _ := sdk.NewIdentifier("iota_names")
31+
nameModule, _ := sdk.NewIdentifier("name")
32+
nameNewFn, _ := sdk.NewIdentifier("new")
33+
lookupFn, _ := sdk.NewIdentifier("lookup")
34+
optionModule, _ := sdk.NewIdentifier("option")
35+
borrowFn, _ := sdk.NewIdentifier("borrow")
36+
targetAddressFn, _ := sdk.NewIdentifier("target_address")
37+
registryModule, _ := sdk.NewIdentifier("registry")
38+
registryName, _ := sdk.NewIdentifier("Registry")
39+
40+
registryType := sdk.NewStructTag(iotaNamesPackageAddress, registryModule, registryName, []*sdk.TypeTag{})
41+
42+
nameRecordModule, _ := sdk.NewIdentifier("name_record")
43+
nameRecordName, _ := sdk.NewIdentifier("NameRecord")
9044
nameRecordType := sdk.NewStructTag(iotaNamesPackageAddress, nameRecordModule, nameRecordName, []*sdk.TypeTag{})
9145

9246
// 1. Get the registry
93-
registryInput := builder.Input(sdk.UnresolvedInputNewShared(iotaNamesObjectId, 365644877, true))
94-
iotaNames := builder.MoveCall(
95-
sdk.Function{
96-
Package: iotaNamesPackageAddress,
97-
Module: iotaNamesModule,
98-
Function: registryFn,
99-
TypeArgs: []*sdk.TypeTag{sdk.TypeTagNewStruct(registryType)},
100-
},
101-
[]*sdk.Argument{registryInput},
47+
builder.MoveCall(
48+
iotaNamesPackageAddress,
49+
iotaNamesModule,
50+
registryModule,
51+
[]*sdk.PtbArgument{sdk.PtbArgumentSharedMut(iotaNamesObjectId)},
52+
[]*sdk.TypeTag{sdk.TypeTagNewStruct(registryType)},
53+
[]string{"iota_names"},
10254
)
10355

10456
// 2. Create name from string
105-
// BCS encode the string: length (as varint) + UTF-8 bytes
106-
nameBytes := []byte(name)
107-
nameLen := len(nameBytes)
108-
var bcsEncodedName []byte
109-
if nameLen < 128 {
110-
// For strings shorter than 128 bytes, length is encoded as single byte
111-
bcsEncodedName = append([]byte{byte(nameLen)}, nameBytes...)
112-
} else {
113-
// For longer strings, we'd need proper varint encoding
114-
// but for this example, the name should be short
115-
panic("String too long for simple BCS encoding")
116-
}
117-
nameInput := builder.Input(sdk.UnresolvedInputNewPure(bcsEncodedName))
118-
nameResult := builder.MoveCall(
119-
sdk.Function{
120-
Package: iotaNamesPackageAddress,
121-
Module: nameModule,
122-
Function: newFn,
123-
TypeArgs: []*sdk.TypeTag{},
124-
},
125-
[]*sdk.Argument{nameInput},
57+
builder.MoveCall(
58+
iotaNamesPackageAddress,
59+
nameModule,
60+
nameNewFn,
61+
[]*sdk.PtbArgument{sdk.PtbArgumentString(name)},
62+
nil,
63+
[]string{"name"},
12664
)
12765

12866
// 3. Lookup name record
129-
nameRecordOption := builder.MoveCall(
130-
sdk.Function{
131-
Package: iotaNamesPackageAddress,
132-
Module: registryFn,
133-
Function: lookupFn,
134-
TypeArgs: []*sdk.TypeTag{},
135-
},
136-
[]*sdk.Argument{iotaNames, nameResult},
67+
builder.MoveCall(
68+
iotaNamesPackageAddress,
69+
registryModule,
70+
lookupFn,
71+
[]*sdk.PtbArgument{sdk.PtbArgumentRes("iota_names"), sdk.PtbArgumentRes("name")},
72+
nil,
73+
[]string{"name_record_opt"},
13774
)
13875

13976
// 4. Borrow name record from option
140-
nameRecord := builder.MoveCall(
141-
sdk.Function{
142-
Package: stdlibAddress,
143-
Module: optionModule,
144-
Function: borrowFn,
145-
TypeArgs: []*sdk.TypeTag{sdk.TypeTagNewStruct(nameRecordType)},
146-
},
147-
[]*sdk.Argument{nameRecordOption},
77+
builder.MoveCall(
78+
stdlibAddress,
79+
optionModule,
80+
borrowFn,
81+
[]*sdk.PtbArgument{sdk.PtbArgumentRes("name_record_opt")},
82+
[]*sdk.TypeTag{sdk.TypeTagNewStruct(nameRecordType)},
83+
[]string{"name_record"},
14884
)
14985

15086
// 5. Get target address from name record
151-
targetAddressOption := builder.MoveCall(
152-
sdk.Function{
153-
Package: iotaNamesPackageAddress,
154-
Module: nameRecordModule,
155-
Function: targetAddressFn,
156-
TypeArgs: []*sdk.TypeTag{},
157-
},
158-
[]*sdk.Argument{nameRecord},
87+
builder.MoveCall(
88+
iotaNamesPackageAddress,
89+
nameRecordModule,
90+
targetAddressFn,
91+
[]*sdk.PtbArgument{sdk.PtbArgumentRes("name_record")},
92+
nil,
93+
[]string{"target_address_opt"},
15994
)
16095

16196
// 6. Borrow address from option
16297
builder.MoveCall(
163-
sdk.Function{
164-
Package: stdlibAddress,
165-
Module: optionModule,
166-
Function: borrowFn,
167-
TypeArgs: []*sdk.TypeTag{sdk.TypeTagNewAddress()},
168-
},
169-
[]*sdk.Argument{targetAddressOption},
98+
stdlibAddress,
99+
optionModule,
100+
borrowFn,
101+
[]*sdk.PtbArgument{sdk.PtbArgumentRes("target_address_opt")},
102+
[]*sdk.TypeTag{sdk.TypeTagNewAddress()},
103+
[]string{"target_address"},
170104
)
171105

172-
builder.SetSender(senderAddress)
173-
builder.SetGasBudget(50000000)
174-
gasPrice, err := client.ReferenceGasPrice(nil)
175-
if err.(*sdk.SdkFfiError) != nil {
176-
log.Fatalf("Failed to get gas price: %v", err)
177-
}
178-
if gasPrice == nil {
179-
log.Fatalf("Missing reference gas price")
180-
}
181-
builder.SetGasPrice(*gasPrice)
182-
183-
txn, err := builder.Finish()
184-
if err != nil {
185-
log.Fatalf("Failed to create transaction: %v", err)
186-
}
187-
188-
skipChecks := true
189-
res, err := client.DryRunTx(txn, &skipChecks)
106+
res, err := builder.DryRun(true)
190107
if err.(*sdk.SdkFfiError) != nil {
191108
log.Fatalf("Failed to dry run transaction: %v", err)
192109
}

bindings/go/examples/generic_move_function/main.go

Lines changed: 17 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
package main
55

66
import (
7-
"encoding/binary"
87
"fmt"
98
"log"
109

@@ -17,64 +16,36 @@ func main() {
1716
sender, _ := sdk.AddressFromHex("0x71b4b4f171b4355ff691b7c470579cf1a926f96f724e5f9a30efc4b5f75d085e")
1817
gas_coin_id, _ := sdk.ObjectIdFromHex("0xa1d009e8dafe20b1cba05e08aea488aafae1f89d892c3eaef6c0994e155e441a")
1918

20-
gas_coin_obj, err := client.Object(gas_coin_id, nil)
21-
if err.(*sdk.SdkFfiError) != nil {
22-
log.Fatalf("Failed to fetch gas coin object: %v", err)
23-
}
24-
gas_coin := sdk.UnresolvedInputFromObject(*gas_coin_obj).WithOwnedKind()
25-
26-
reference_gas_price, err := client.ReferenceGasPrice(nil)
27-
if err.(*sdk.SdkFfiError) != nil {
28-
log.Fatalf("Failed to fetch reference gas price: %v", err)
29-
}
30-
31-
builder := sdk.NewTransactionBuilder()
19+
builder := sdk.TransactionBuilderInit(sender, client)
3220

3321
addr1, _ := sdk.AddressFromHex("0xde49ea53fbadee67d3e35a097cdbea210b659676fc680a0b0c5f11d0763d375e")
3422
addr2, _ := sdk.AddressFromHex("0xe512234aa4ef6184c52663f09612b68f040dd0c45de037d96190a071ca5525b3")
3523

36-
addr1_arg := builder.Input(sdk.UnresolvedInputNewPure(addr1.ToBytes()))
37-
addr2_arg := builder.Input(sdk.UnresolvedInputNewPure(addr2.ToBytes()))
38-
39-
address_type_tag := sdk.TypeTagNewAddress()
40-
balance_type_tag := sdk.TypeTagNewU64()
41-
42-
buf := make([]byte, 8)
43-
binary.LittleEndian.PutUint64(buf, 10_000_000)
44-
bal1_arg := builder.Input(sdk.UnresolvedInputNewPure(buf))
45-
binary.LittleEndian.PutUint64(buf, 20_000_000)
46-
bal2_arg := builder.Input(sdk.UnresolvedInputNewPure(buf))
24+
builder.MakeMoveVec([]*sdk.PtbArgument{sdk.PtbArgumentAddress(addr1), sdk.PtbArgumentAddress(addr2)}, sdk.TypeTagNewAddress(), "addresses")
25+
builder.MakeMoveVec([]*sdk.PtbArgument{sdk.PtbArgumentU64(10_000_000), sdk.PtbArgumentU64(20_000_000)}, sdk.TypeTagNewU64(), "amounts")
4726

48-
arg1 := builder.MakeMoveVec(&address_type_tag, []*sdk.Argument{addr1_arg, addr2_arg})
49-
arg2 := builder.MakeMoveVec(&balance_type_tag, []*sdk.Argument{bal1_arg, bal2_arg})
50-
51-
package_name, _ := sdk.AddressFromHex("0x2")
27+
package_id, _ := sdk.AddressFromHex("0x2")
5228
module_name, _ := sdk.NewIdentifier("vec_map")
5329
function_name, _ := sdk.NewIdentifier("from_keys_values")
5430

55-
function := sdk.Function{Package: package_name,
56-
Module: module_name,
57-
Function: function_name,
58-
TypeArgs: []*sdk.TypeTag{address_type_tag, balance_type_tag},
59-
}
60-
61-
builder.MoveCall(function, []*sdk.Argument{arg1, arg2})
31+
builder.MoveCall(
32+
package_id,
33+
module_name,
34+
function_name,
35+
[]*sdk.PtbArgument{sdk.PtbArgumentRes("addresses"), sdk.PtbArgumentRes("amounts")},
36+
[]*sdk.TypeTag{sdk.TypeTagNewAddress(), sdk.TypeTagNewU64()},
37+
nil,
38+
)
6239

63-
builder.SetGasBudget(50_000_000)
64-
builder.SetGasPrice(*reference_gas_price)
65-
builder.SetSender(sender)
66-
builder.AddGasObjects([]*sdk.UnresolvedInput{gas_coin})
40+
builder.Gas(gas_coin_id).GasBudget(1000000000)
6741

68-
txn, err := builder.Finish()
69-
if err != nil {
70-
log.Fatalf("Failed to create transaction: %v", err)
42+
res, err := builder.DryRun(false)
43+
if err.(*sdk.SdkFfiError) != nil {
44+
log.Fatalf("Failed to call generic Move function: %v", err)
7145
}
7246

73-
skipChecks := false
74-
res, err := client.DryRunTx(txn, &skipChecks)
75-
7647
if res.Error != nil {
77-
log.Fatalf("Failed to call generic Move function: %v", err)
48+
log.Fatalf("Failed to call generic Move function: %v", *res.Error)
7849
}
7950

8051
fmt.Print("Successfully called generic Move function")

0 commit comments

Comments
 (0)