Skip to content

Commit

Permalink
[scripts] Add example for FA
Browse files Browse the repository at this point in the history
  • Loading branch information
gregnazario committed Nov 4, 2024
1 parent 79917e8 commit ffccf23
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ adheres to the format set out by [Keep a Changelog](https://keepachangelog.com/e

# Unreleased
- Add better error messages around script argument parsing
- Add example for scripts with FA

# v1.0.0 (10/28/2024)
- [`Fix`] Paginate transactions properly if no given start version
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ You can read more about the Go SDK documentation on [aptos.dev](https://aptos.de
### TODO

- [ ] Multi-agent example
- [ ] Script Example
- [x] Script Example
- [ ] Digital assets / NFTs example
- [ ] Transaction parsing example (by blocks)

Expand Down
79 changes: 76 additions & 3 deletions examples/fungible_asset/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ import (
)

const testEd25519PrivateKey = "0xc5338cd251c22daa8c9c9cc94f498cc8a5c7e1d2e75287a5dda91096fe64efa5"
const rupeePublisherAddress = "0x978c213990c4833df71548df7ce49d54c759d6b6d932de22b24d56060b7af2aa"

// These come from fungible_asset.json
const metadata = "0x0572757065650100000000000000004038393534453933384132434137314536433445313139434230333341363036453341333537424245353843354430304235453132354236383238423745424331e7011f8b08000000000002ff3d8ecd6ec4200c84ef3cc58a7b13427ea9d4432f7d8928aa0c7636d136100149fbf885ed764ff68cbeb167dcc1dce04a13b3b0d1e5edc2fdb1137176920fabb3d9a90a5108cee0888bf32139e3c4d808889e42a030b17be4331b19173faa1f8cac6aa5846986bac6b9afda6648c350a3b06d4cdf2aec7487aa9648526ad960db894ee81e6609c0d379a49d2c92352b85e27d8f2e7cf8d4f0dbf9dbc4ae6bcc9f9618f7f05a96492e872e8cdb4ac8e4cb17e8f0588df3542480334f670e6db05a4b498743e37a6ffc476eeea472fe7ff2883f3567bf9aa419822b010000010572757065650000000300000000000000000000000000000000000000000000000000000000000000010e4170746f734672616d65776f726b00000000000000000000000000000000000000000000000000000000000000010b4170746f735374646c696200000000000000000000000000000000000000000000000000000000000000010a4d6f76655374646c696200"
const bytecode = "0xa11ceb0b060000000c01000e020e30033e850104c3010605c901980107e102c30408a4074006e407950110f9088a010a830a120c950ae1020df60c060000010101020103010401050106000708000110060001120600011406000212060002170600011a0800021b07010001021e02000323070100000625070000080001000009010200000a030100000b030100000c000100000d040100000e05010005180302000219070200021c02090108021d0a0b010804080c0100021f0e0f000220101100022110120002221301000324011501000626161700042718010001281019000121101a000129101b00022a101c00040c1d0100042b1e0100042c1f010009080a08101403060c050300010501060c03060c050104060c050503030505050206050a02010806010b07010900020b070109000501010306080305030708030808080108050c0804080202060c0a0201080801060808010805010804010608040104010b09010900010a0201080a070608080b090104080a080a02080a080a010801010802010803010c030608010503030608020501040608020505030572757065650e66756e6769626c655f6173736574066f626a656374066f7074696f6e167072696d6172795f66756e6769626c655f73746f7265067369676e657206737472696e6709527570656552656673046275726e0a66615f616464726573730b696e69745f6d6f64756c650a696e697469616c697a65046d696e740a7365745f667265657a65087472616e73666572086d696e745f726566074d696e745265660c7472616e736665725f7265660b5472616e73666572526566086275726e5f726566074275726e526566106f626a5f7472616e736665725f7265660e6f626a5f657874656e645f72656609457874656e645265660a616464726573735f6f66156372656174655f6f626a6563745f61646472657373084d65746164617461064f626a65637411616464726573735f746f5f6f626a6563740869735f6f776e65720e436f6e7374727563746f72526566136372656174655f6e616d65645f6f626a6563741367656e65726174655f657874656e645f7265661567656e65726174655f7472616e736665725f7265661864697361626c655f756e67617465645f7472616e73666572064f7074696f6e046e6f6e6506537472696e6704757466382b6372656174655f7072696d6172795f73746f72655f656e61626c65645f66756e6769626c655f61737365741167656e65726174655f6d696e745f7265661167656e65726174655f6275726e5f7265660f67656e65726174655f7369676e65720f7365745f66726f7a656e5f666c6167117472616e736665725f776974685f726566978c213990c4833df71548df7ce49d54c759d6b6d932de22b24d56060b7af2aa0000000000000000000000000000000000000000000000000000000000000001030801000000000000000201020a02060552757065650a021413527570656573417265466f7254657374696e670a02060552555045450a023635697066733a2f2f516d585342534c6f337744426e6133314d4c56784b4a356f424a486b676f444d7845676a527a39745044665a506e0520978c213990c4833df71548df7ce49d54c759d6b6d932de22b24d56060b7af2aa0a020100126170746f733a3a6d657461646174615f7631760101000000000000000b455f4e4f545f4f574e45522a43616c6c6572206973206e6f74206f776e6572206f6620746865206d65746164617461206f626a6563740109527570656552656673010301183078313a3a6f626a6563743a3a4f626a65637447726f7570010a66615f616464726573730101000002050f08011108021308031508041608050000040100061a0b0011070c0507060c030e030703110838000b053801040d050f07002707060c040e04070311082b0010000b010b02110b0201010000020607060c000e0007031108020200000001030b00110302030000000d2d0b000703110c0c020e02110d0c040e02110e0c060e06110f0e02380207021111070411110701070511110707111111120e0211130c030e0211140c070e0211150c010e0211160c050e050b030b070b010b060b0412002d00020400040100061a0b0011070c0507060c030e030703110838000b053801040d050f07002707060c040e04070311082b0010010b010b021117020500040100061a0b0011070c0507060c030e030703110838000b053801040d050f07002707060c040e04070311082b0010020b010b021118020600040100061b0b0011070c0607060c040e040703110838000b063801040d050f07002707060c050e05070311082b0010020b010b020b0311190200020000000100"
const TransferAmount = uint64(1_000)
const FundAmount = uint64(100_000_000)

func example(networkConfig aptos.NetworkConfig) {
// Create a client for Aptos
Expand All @@ -34,7 +37,8 @@ func example(networkConfig aptos.NetworkConfig) {
}

// Fund the sender with the faucet to create it on-chain
err = client.Fund(sender.Address, 100_000_000)
println("SENDER: ", sender.Address.String())
err = client.Fund(sender.Address, FundAmount)
if err != nil {
panic("Failed to fund sender:" + err.Error())
}
Expand Down Expand Up @@ -87,7 +91,7 @@ func example(networkConfig aptos.NetworkConfig) {
}

// Let's mint and transfer some coins
amount, err := bcs.SerializeU64(10000000)
amount, err := bcs.SerializeU64(FundAmount)
if err != nil {
panic("Failed to serialize amount:" + err.Error())
}
Expand Down Expand Up @@ -127,7 +131,7 @@ func example(networkConfig aptos.NetworkConfig) {
if err != nil {
panic("Failed to get balance:" + err.Error())
}
transferTxn, err := faClient.TransferPrimaryStore(sender, *receiver, 100)
transferTxn, err := faClient.TransferPrimaryStore(sender, *receiver, TransferAmount)
if err != nil {
panic("Failed to create primary store transfer transaction:" + err.Error())
}
Expand All @@ -146,6 +150,75 @@ func example(networkConfig aptos.NetworkConfig) {
}

fmt.Printf("Receiver Before transfer: %d, after transfer: %d\n", receiverBeforeBalance, receiverAfterBalance)

// Now run a script version
fmt.Printf("\n== Now running script version ==\n")
runScript(client, sender, receiver, faMetadataAddress)

receiverAfterAfterBalance, err := faClient.PrimaryBalance(receiver)
if err != nil {
panic("Failed to get store balance:" + err.Error())
}
fmt.Printf("After Script: Receiver Before transfer: %d, after transfer: %d\n", receiverAfterBalance, receiverAfterAfterBalance)
}

const TransferScript = "0xa11ceb0b0700000a0701000a020a0a03141a042e040532240756870108dd01200000000100020003000403050701000102060b0003070304010801000803060001010903050001040a07050108010002030204060c050503010b000108010108010105010b0001090000010104060c0b000109000503076163636f756e740d6170746f735f6163636f756e740e66756e6769626c655f6173736574066f626a656374167072696d6172795f66756e6769626c655f73746f7265064f626a656374084d6574616461746111616464726573735f746f5f6f626a656374096578697374735f61740e6372656174655f6163636f756e74087472616e7366657200000000000000000000000000000000000000000000000000000000000000010000010f0b0138000c040a0211012004090a0211020b000b040b020b03380102"

func runScript(client *aptos.Client, alice *aptos.Account, bob *aptos.AccountAddress, faMetadataAddress *aptos.AccountAddress) {
scriptBytes, err := aptos.ParseHex(TransferScript)
if err != nil {
panic("Failed to parse script:" + err.Error())
}

// 1. Build transaction
rawTxn, err := client.BuildTransaction(alice.AccountAddress(), aptos.TransactionPayload{
Payload: &aptos.Script{
Code: scriptBytes,
ArgTypes: []aptos.TypeTag{},
Args: []aptos.ScriptArgument{
{Variant: aptos.ScriptArgumentAddress, Value: *faMetadataAddress},
{Variant: aptos.ScriptArgumentAddress, Value: *bob},
{Variant: aptos.ScriptArgumentU64, Value: TransferAmount},
},
}},
)

if err != nil {
panic("Failed to build transaction:" + err.Error())
}

// 2. Simulate transaction (optional)
// This is useful for understanding how much the transaction will cost
// and to ensure that the transaction is valid before sending it to the network
// This is optional, but recommended
simulationResult, err := client.SimulateTransaction(rawTxn, alice)
if err != nil {
panic("Failed to simulate transaction:" + err.Error())
}
fmt.Printf("\n=== Simulation ===\n")
fmt.Printf("Gas unit price: %d\n", simulationResult[0].GasUnitPrice)
fmt.Printf("Gas used: %d\n", simulationResult[0].GasUsed)
fmt.Printf("Total gas fee: %d\n", simulationResult[0].GasUsed*simulationResult[0].GasUnitPrice)
fmt.Printf("Status: %s\n", simulationResult[0].VmStatus)

// 3. Sign transaction
signedTxn, err := rawTxn.SignedTransaction(alice)
if err != nil {
panic("Failed to sign transaction:" + err.Error())
}

// 4. Submit transaction
submitResult, err := client.SubmitTransaction(signedTxn)
if err != nil {
panic("Failed to submit transaction:" + err.Error())
}
txnHash := submitResult.Hash

// 5. Wait for the transaction to complete
_, err = client.WaitForTransaction(txnHash)
if err != nil {
panic("Failed to wait for transaction:" + err.Error())
}
}

// main This example shows how to create and transfer fungible assets
Expand Down
1 change: 1 addition & 0 deletions examples/move/fa_account_script/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/
8 changes: 8 additions & 0 deletions examples/move/fa_account_script/Move.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "fa_util_script"
version = "1.0.0"

[dependencies.AptosFramework]
git = "https://github.com/aptos-labs/aptos-core.git"
rev = "mainnet"
subdir = "aptos-move/framework/aptos-framework"
19 changes: 19 additions & 0 deletions examples/move/fa_account_script/sources/fa_util.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// To compile run `aptos move compile`
//
// To get the bytecode `xxd -c 1000000 -p build/fa_util_script/bytecode_scripts/transfer.mv`
script {
use aptos_framework::account;
use aptos_framework::aptos_account;
use aptos_framework::object;
use aptos_framework::primary_fungible_store;
use aptos_framework::fungible_asset::Metadata;

fun transfer(caller: &signer, metadata_address: address, receiver: address, amount: u64) {
let metadata_object = object::address_to_object<Metadata>(metadata_address);
if (!account::exists_at(receiver)) {
aptos_account::create_account(receiver)
};

primary_fungible_store::transfer(caller, metadata_object, receiver, amount);
}
}

0 comments on commit ffccf23

Please sign in to comment.