Skip to content

Commit d8d9701

Browse files
committed
Add SerializeUleb128 function and example script for transaction arguments
1 parent b1b101e commit d8d9701

File tree

2 files changed

+323
-0
lines changed

2 files changed

+323
-0
lines changed

bcs/serializer.go

+6
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,12 @@ func SerializeBytes(input []byte) ([]byte, error) {
303303
})
304304
}
305305

306+
func SerializeUleb128(input uint32) ([]byte, error) {
307+
return SerializeSingle(func(ser *Serializer) {
308+
ser.Uleb128(input)
309+
})
310+
}
311+
306312
// SerializeSingle is a convenience function, to not have to create a serializer to serialize one value
307313
//
308314
// Here's an example for handling a nested byte array
+317
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,317 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"math/big"
6+
7+
"github.com/aptos-labs/aptos-go-sdk"
8+
"github.com/aptos-labs/aptos-go-sdk/bcs"
9+
"github.com/aptos-labs/aptos-go-sdk/internal/util"
10+
)
11+
12+
/*
13+
script {
14+
use std::string::String;
15+
16+
fun main(
17+
bool: bool,
18+
u8: u8,
19+
u16: u16,
20+
u32: u32,
21+
u64: u64,
22+
u128: u128,
23+
u256: u256,
24+
address: address,
25+
string: String,
26+
vec_u8: vector<u8>,
27+
vec_u16: vector<u16>,
28+
vec_u32: vector<u32>,
29+
vec_u64: vector<u64>,
30+
vec_u128: vector<u128>,
31+
vec_u256: vector<u256>,
32+
vec_address: vector<address>,
33+
vec_string: vector<String>,
34+
){
35+
36+
}
37+
}
38+
*/
39+
40+
const scriptBytes = "a11ceb0b0700000a0601000202020405061d07231c083f40107f1f0103000207001101020d0e03040f0508000a020a0d0a0e0a030a040a0f0a050a080000083c53454c463e5f30046d61696e06537472696e6706737472696e67ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000114636f6d70696c6174696f6e5f6d65746164617461090003322e3003322e310000010102"
41+
const FundAmount = uint64(100_000_000)
42+
43+
func example(networkConfig aptos.NetworkConfig) {
44+
// Create a client for Aptos
45+
client, err := aptos.NewClient(networkConfig)
46+
if err != nil {
47+
panic("Failed to create client:" + err.Error())
48+
}
49+
50+
// Create a sender
51+
sender, err := aptos.NewEd25519Account()
52+
if err != nil {
53+
panic("Failed to create sender:" + err.Error())
54+
}
55+
56+
// Fund the sender with the faucet to create it on-chain
57+
println("SENDER: ", sender.Address.String())
58+
err = client.Fund(sender.Address, FundAmount)
59+
if err != nil {
60+
panic("Failed to fund sender:" + err.Error())
61+
}
62+
63+
// Now run a script version
64+
fmt.Printf("\n== Now running script version ==\n")
65+
runScript(client, sender)
66+
67+
if err != nil {
68+
panic("Failed to get store balance:" + err.Error())
69+
}
70+
// fmt.Printf("After Script: Receiver Before transfer: %d, after transfer: %d\n", receiverAfterBalance, receiverAfterAfterBalance)
71+
}
72+
73+
func runScript(client *aptos.Client, alice *aptos.Account) {
74+
scriptBytes, err := aptos.ParseHex(scriptBytes)
75+
if err != nil {
76+
panic("Failed to parse script:" + err.Error())
77+
}
78+
79+
u128_arg ,err:= util.StrToBigInt("128")
80+
if err != nil {
81+
panic("Failed to convert u128:" + err.Error())
82+
}
83+
84+
u256_arg ,err:= util.StrToBigInt("256")
85+
if err != nil {
86+
panic("Failed to convert u256:" + err.Error())
87+
}
88+
89+
vec_u16 := []uint16{1, 2, 3, 4, 5}
90+
91+
vec_u16_len, err := bcs.SerializeUleb128(uint32(len(vec_u16)));
92+
if err != nil {
93+
panic("Failed to serialize uleb128:" + err.Error())
94+
}
95+
96+
var vec_u16_arg []byte
97+
vec_u16_arg = append(vec_u16_arg, vec_u16_len...)
98+
for _, v := range vec_u16 {
99+
bytes, err := bcs.SerializeU16(v)
100+
if err != nil {
101+
panic("Failed to serialize u16:" + err.Error())
102+
}
103+
vec_u16_arg = append(vec_u16_arg, bytes...)
104+
}
105+
106+
vec_u32 := []uint32{1, 2, 3, 4, 5}
107+
vec_u32_len, err := bcs.SerializeUleb128(uint32(len(vec_u32)));
108+
if err != nil {
109+
panic("Failed to serialize uleb128:" + err.Error())
110+
}
111+
var vec_u32_arg []byte
112+
vec_u32_arg = append(vec_u32_arg, vec_u32_len...)
113+
for _, v := range vec_u32 {
114+
bytes, err := bcs.SerializeU32(v)
115+
if err != nil {
116+
panic("Failed to serialize u32:" + err.Error())
117+
}
118+
vec_u32_arg = append(vec_u32_arg, bytes...)
119+
}
120+
121+
vec_u64 := []uint64{1, 2, 3, 4, 5}
122+
vec_u64_len, err := bcs.SerializeUleb128(uint32(len(vec_u64)));
123+
if err != nil {
124+
panic("Failed to serialize uleb128:" + err.Error())
125+
}
126+
var vec_u64_arg []byte
127+
vec_u64_arg = append(vec_u64_arg, vec_u64_len...)
128+
for _, v := range vec_u64 {
129+
bytes, err := bcs.SerializeU64(v)
130+
if err != nil {
131+
panic("Failed to serialize u64:" + err.Error())
132+
}
133+
vec_u64_arg = append(vec_u64_arg, bytes...)
134+
}
135+
136+
vec_u128 := []big.Int{*big.NewInt(1), *big.NewInt(1),*big.NewInt(2), *big.NewInt(3), *big.NewInt(4)}
137+
vec_u128_len, err := bcs.SerializeUleb128(uint32(len(vec_u128)));
138+
if err != nil {
139+
panic("Failed to serialize uleb128:" + err.Error())
140+
}
141+
var vec_u128_arg []byte
142+
vec_u128_arg = append(vec_u128_arg, vec_u128_len...)
143+
for _, v := range vec_u128 {
144+
bytes, err := bcs.SerializeU128(v)
145+
if err != nil {
146+
panic("Failed to serialize u128:" + err.Error())
147+
}
148+
vec_u128_arg = append(vec_u128_arg, bytes...)
149+
}
150+
151+
vec_u256 := []big.Int{*big.NewInt(1), *big.NewInt(1),*big.NewInt(2), *big.NewInt(3), *big.NewInt(4)}
152+
vec_u256_len, err := bcs.SerializeUleb128(uint32(len(vec_u256)));
153+
if err != nil {
154+
panic("Failed to serialize uleb128:" + err.Error())
155+
}
156+
var vec_u256_arg []byte
157+
vec_u256_arg = append(vec_u256_arg, vec_u256_len...)
158+
for _, v := range vec_u256 {
159+
bytes, err := bcs.SerializeU256(v)
160+
if err != nil {
161+
panic("Failed to serialize u256:" + err.Error())
162+
}
163+
vec_u256_arg = append(vec_u256_arg, bytes...)
164+
}
165+
166+
vec_address := []aptos.AccountAddress{alice.AccountAddress(), alice.AccountAddress(), alice.AccountAddress(), alice.AccountAddress(), alice.AccountAddress()}
167+
vec_address_len, err := bcs.SerializeUleb128(uint32(len(vec_address)));
168+
if err != nil {
169+
panic("Failed to serialize uleb128:" + err.Error())
170+
}
171+
var vec_address_arg []byte
172+
vec_address_arg = append(vec_address_arg, vec_address_len...)
173+
for _, v := range vec_address {
174+
ser := bcs.Serializer{};
175+
v.MarshalBCS(&ser)
176+
bytes := ser.ToBytes()
177+
vec_address_arg = append(vec_address_arg, bytes...)
178+
}
179+
180+
vec_string := []string{"string", "string", "string", "string", "string"}
181+
vec_string_len, err := bcs.SerializeUleb128(uint32(len(vec_string)));
182+
if err != nil {
183+
panic("Failed to serialize uleb128:" + err.Error())
184+
}
185+
var vec_string_arg []byte
186+
vec_string_arg = append(vec_string_arg, vec_string_len...)
187+
188+
for _, v := range vec_string {
189+
string_len, err := bcs.SerializeUleb128(uint32(len([]byte(v))));
190+
if err != nil {
191+
panic("Failed to serialize uleb128:" + err.Error())
192+
}
193+
vec_string_arg = append(vec_string_arg, string_len...)
194+
vec_string_arg = append(vec_string_arg, []byte(v)...)
195+
}
196+
197+
// 1. Build transaction
198+
rawTxn, err := client.BuildTransaction(alice.AccountAddress(), aptos.TransactionPayload{
199+
Payload: &aptos.Script{
200+
Code: scriptBytes,
201+
ArgTypes: []aptos.TypeTag{ },
202+
Args: []aptos.ScriptArgument{
203+
{
204+
Variant: aptos.ScriptArgumentBool,
205+
Value: bool(true),
206+
},
207+
{
208+
Variant: aptos.ScriptArgumentU8,
209+
Value: uint8(8),
210+
},
211+
{
212+
Variant: aptos.ScriptArgumentU16,
213+
Value: uint16(16),
214+
},
215+
{
216+
Variant: aptos.ScriptArgumentU32,
217+
Value: uint32(32),
218+
},
219+
{
220+
Variant: aptos.ScriptArgumentU64,
221+
Value: uint64(64),
222+
},
223+
{
224+
Variant: aptos.ScriptArgumentU128,
225+
Value: *u128_arg,
226+
},
227+
{
228+
Variant: aptos.ScriptArgumentU256,
229+
Value: *u256_arg,
230+
},
231+
{
232+
Variant: aptos.ScriptArgumentAddress,
233+
Value: alice.Address,
234+
},
235+
{
236+
Variant: aptos.ScriptArgumentU8Vector,
237+
Value: []byte("string"),
238+
},
239+
{
240+
Variant: aptos.ScriptArgumentU8Vector,
241+
Value: []byte{1, 2, 3, 4, 5},
242+
},
243+
{
244+
Variant: aptos.ScriptArgumentSerialized,
245+
Value: &bcs.Serialized{Value: vec_u16_arg},
246+
},
247+
{
248+
Variant: aptos.ScriptArgumentSerialized,
249+
Value: &bcs.Serialized{Value: vec_u32_arg},
250+
},
251+
{
252+
Variant: aptos.ScriptArgumentSerialized,
253+
Value: &bcs.Serialized{Value: vec_u64_arg},
254+
},
255+
{
256+
Variant: aptos.ScriptArgumentSerialized,
257+
Value: &bcs.Serialized{Value: vec_u128_arg},
258+
},
259+
{
260+
Variant: aptos.ScriptArgumentSerialized,
261+
Value: &bcs.Serialized{Value: vec_u256_arg},
262+
},
263+
{
264+
Variant: aptos.ScriptArgumentSerialized,
265+
Value: &bcs.Serialized{Value: vec_address_arg},
266+
},
267+
{
268+
Variant: aptos.ScriptArgumentSerialized,
269+
Value: &bcs.Serialized{Value: vec_string_arg},
270+
},
271+
},
272+
}})
273+
if err != nil {
274+
panic("Failed to build multiagent raw transaction:" + err.Error())
275+
}
276+
277+
278+
if err != nil {
279+
panic("Failed to build transaction:" + err.Error())
280+
}
281+
282+
// 2. Simulate transaction (optional)
283+
// This is useful for understanding how much the transaction will cost
284+
// and to ensure that the transaction is valid before sending it to the network
285+
// This is optional, but recommended
286+
simulationResult, err := client.SimulateTransaction(rawTxn, alice)
287+
if err != nil {
288+
panic("Failed to simulate transaction:" + err.Error())
289+
}
290+
fmt.Printf("\n=== Simulation ===\n")
291+
fmt.Printf("Gas unit price: %d\n", simulationResult[0].GasUnitPrice)
292+
fmt.Printf("Gas used: %d\n", simulationResult[0].GasUsed)
293+
fmt.Printf("Total gas fee: %d\n", simulationResult[0].GasUsed*simulationResult[0].GasUnitPrice)
294+
fmt.Printf("Status: %s\n", simulationResult[0].VmStatus)
295+
296+
// 3. Sign transaction
297+
signedTxn, err := rawTxn.SignedTransaction(alice)
298+
if err != nil {
299+
panic("Failed to sign transaction:" + err.Error())
300+
}
301+
302+
// 4. Submit transaction
303+
submitResult, err := client.SubmitTransaction(signedTxn)
304+
if err != nil {
305+
panic("Failed to submit transaction:" + err.Error())
306+
}
307+
txnHash := submitResult.Hash
308+
309+
// 5. Wait for the transaction to complete
310+
_, err = client.WaitForTransaction(txnHash)
311+
if err != nil {
312+
panic("Failed to wait for transaction:" + err.Error())
313+
}
314+
}
315+
func main() {
316+
example(aptos.DevnetConfig)
317+
}

0 commit comments

Comments
 (0)