Order Platform
Endless Go SDK Quick Start
1. Order Platform Move Contract
1.1 Contract Overview
The contract provides a decentralized framework for creating and managing orders within an e-commerce ecosystem. It defines the complete lifecycle of an order, from creation to completion, including payment, shipping, and cancellation. The system is built on the Endless blockchain, utilizing EndlessCoin
for payments and a table-based storage system for scalability.
1.2 Core Concepts
1.2.1 Order Lifecycle (State Machine)
The core of the contract is a state machine that represents the lifecycle of an order. Each order progresses through a series of statuses, and transitions are governed by specific rules and function calls.
The statuses are defined as constants:
STATUS_PENDING_PAYMENT
(0): The initial state after an order is created. Awaiting payment from the buyer.STATUS_PAID
(1): The buyer has successfully transferred the funds to the seller.STATUS_SHIPPED
(2): The seller has marked the order as shipped.STATUS_COMPLETED
(3): The buyer has confirmed receipt of the item. (Note: The function for this is currently commented out but is part of the intended design).STATUS_CANCELLED
(4): The order has been cancelled by either the buyer or the seller under specific conditions.
A typical successful order flow is: PENDING_PAYMENT
-> PAID
-> SHIPPED
-> COMPLETED
1.2.2 Roles
There are two primary roles in this system:
Buyer: The user who creates and pays for the order.
Seller: The user who receives payment and ships the item.
Each state-changing function includes assertions to ensure that the transaction signer has the correct role for the intended action (e.g., only the buyer can pay, only the seller can ship).
1.2.3 Economy
All financial transactions are conducted using the native EndlessCoin(EDS)
. Prices and payments are specified in veins
, the smallest unit of EndlessCoin
, to ensure precision and avoid floating-point issues. 1 EDS = 100_000_000 Veins.
1.3 Data Structures (On-Chain State)
The contract's state is managed by two singleton resources, stored under the deployer's account (@order_platform
).
1.3.1 Resources
OrderCounter
:A singleton resource that ensures every order receives a unique, sequential ID.
next_order_id: u64
: A counter that is incremented each time a new order is created.
Orders
:A singleton resource that acts as the central repository for all orders.
orders: Table<u64, Order>
: A scalable map (Table
) that links a uniqueorder_id
(u64) to its correspondingOrder
struct. This allows for efficient lookups, insertions, and modifications.
1.3.2 Structs
Order
:The primary data structure representing an individual order. It has
store
anddrop
abilities, meaning it can be stored in global storage but cannot be copied.order_id: u64
: Unique identifier.buyer: address
: The address of the buyer.seller: address
: The address of the seller.item_id: String
: A string identifier for the product.quantity: u128
: The number of items ordered.unit_price: u128
: The price per item in Veins.total_price: u128
: The calculated total price (quantity * unit_price
).status: u8
: The current status of the order, corresponding to the status constants.
OrderData
:A read-only representation of an order's data. It has
copy
,drop
, andstore
abilities, making it suitable for returning from#[view]
functions. Its structure mirrors theOrder
struct.
1.4 Events
The contract emits events at key points in the order lifecycle. This allows off-chain services, indexers, and user interfaces to monitor and react to on-chain activity without needing to query the state directly.
OrderCreatedEvent
: Emitted whencreate_order
is successfully called.OrderPaidEvent
: Emitted whenpay_order
is successfully called.OrderShippedEvent
: Emitted whenship_order
is successfully called.OrderCancelledEvent
: Emitted whencancel_order
is successfully called.OrderCompletedEvent
: Emitted when an order is marked as complete.
1.5 Functions (Module API)
1.5.1 Initialization Function
init_module(deployer: &signer)
:A private function that must be called once by the module deployer to initialize the
OrderCounter
andOrders
resources.It includes an assertion to prevent re-initialization.
1.5.2 Entry Functions (State-Changing)
create_order(...)
:Allows a
buyer
to create a new order.It calculates the
total_price
, assigns a neworder_id
, stores theOrder
struct in theOrders
table, and emits anOrderCreatedEvent
.
pay_order(...)
:Allows the
buyer
to pay for an order that is in theSTATUS_PENDING_PAYMENT
.Preconditions: The order must exist, the signer must be the buyer, the status must be
PENDING_PAYMENT
, and the payment amount must match thetotal_price
.It transfers
EndlessCoin
from the buyer to the seller, updates the order status toSTATUS_PAID
, and emits anOrderPaidEvent
.
ship_order(...)
:Allows the
seller
to mark a paid order as shipped.Preconditions: The order must exist, the signer must be the seller, and the status must be
STATUS_PAID
.It updates the order status to
STATUS_SHIPPED
and emits anOrderShippedEvent
.
cancel_order(...)
:Allows a
buyer
orseller
to cancel an order based on specific rules.Preconditions:
A
buyer
can cancel if the status isPENDING_PAYMENT
orPAID
.A
seller
can cancel only if the status isPENDING_PAYMENT
.The signer must be either the buyer or the seller.
It updates the order status to
STATUS_CANCELLED
and emits anOrderCancelledEvent
.Note: This function does not currently handle refund logic for paid cancellations. This would be a required enhancement for a production system.
1.5.3 View Functions (Read-Only)
get_order_details(order_id: u64): OrderData
:A public, read-only function that returns the
OrderData
for a givenorder_id
.It asserts that the order exists.
get_order_status(order_id: u64): u8
:A public, read-only function that returns just the
status
of a givenorder_id
.
1.6 Error Handling
The module defines a set of comprehensive error codes to provide clear reasons for transaction failures.
E_NOT_INITIALIZED
(1): The module has not been initialized.E_ORDER_NOT_FOUND
(2): The specifiedorder_id
does not exist.E_INVALID_ORDER_STATUS
(3): The action is not allowed in the order's current state.E_INSUFFICIENT_FUNDS
(4): The buyer does not have enough coins to pay.E_SENDER_NOT_BUYER
(5): The transaction was signed by an address other than the buyer's.E_SENDER_NOT_SELLER
(6): The transaction was signed by an address other than the seller's.E_PAYMENT_AMOUNT_MISMATCH
(7): The payment amount does not match the order's total price.E_COIN_TRANSFER_FAILED
(9): A generic error for coin transfer failures.E_NOT_AUTHORIZED
(10): The signer is neither the buyer nor the seller for a restricted action.
1.7 Future Enhancements
Implement
complete_order
: Add the entry function to allow buyers to mark an order asSTATUS_COMPLETED
.Refund on Cancellation: Implement logic in
cancel_order
to automatically refund the buyer if aPAID
order is cancelled.Reputation System: Add a mechanism for buyers and sellers to rate each other after an order is completed.
Dispute Resolution: Introduce a mechanism for handling disputes, potentially involving a trusted third party or a decentralized arbitration process.
1.8 Deploy Contract
1.8.1 Create project folder
{path}>mkdir endless-orders
{path}>cd endless-orders
1.8.2 Create move contract folder
{path}\endless-orders>mkdir move
{path}\endless-orders>cd move
1.8.3 Init contract project
{path}\endless-orders\move>endless move init --name endless-orders
Success
{path}\endless-orders\move>dir
2025/07/02 11:14 <DIR> .
2025/07/02 11:13 <DIR> ..
2025/07/02 11:14 253 Move.toml
2025/07/02 11:14 <DIR> scripts
2025/07/02 11:14 <DIR> sources
2025/07/02 11:14 <DIR> tests
1.8.4 Implementing the contract according to the above design
The complete contract is in the file {path}\endless-orders\move\sources\orders.move
1.8.5 Craete contract deplay account
{path}\endless-orders\move>endless init
Configuring for profile default
Choose network from [testnet, mainnet, local, custom | defaults to testnet]
No network given, using testnet...
Enter your private key as a hex literal (0x...) [Current: None | No input: Generate new key (or keep one if present)]
No key given, generating key...
Account 0xdcf462ef1bad8ed0901043126048acdbf6446f486eee2a38a12ddf8b727a2cc6 doesn't exist, creating it and funding it with 100000000 Veins
Account 0xdcf462ef1bad8ed0901043126048acdbf6446f486eee2a38a12ddf8b727a2cc6 funded successfully
---
Endless CLI is now set up for account 0xdcf462ef1bad8ed0901043126048acdbf6446f486eee2a38a12ddf8b727a2cc6 as profile default! Run `endless --help` for more information about commands
Success
1.8.6 Modify contract address
Modify [addresses] field in {path}\endless-orders\move\Move.toml
[addresses]
order_platform = "FsWq9ZonkCHLZfoRG3Ci8PGr7ps3Mo5mqLGyE1CyRNhb"
"0xdcf462ef1bad8ed0901043126048acdbf6446f486eee2a38a12ddf8b727a2cc6"'s base58 format.
1.8.7 Deploy contract
{path}\endless-orders\move>endless move publish
Compiling, may take a little while to download git dependencies...
INCLUDING DEPENDENCY EndlessFramework
INCLUDING DEPENDENCY EndlessStdlib
INCLUDING DEPENDENCY MoveStdlib
BUILDING endless-orders
package size 5577 bytes
Do you want to submit a transaction for a range of [402000 - 603000] Veins at a gas unit price of 100 Veins? [yes/no] >
yes
transaction_hash:8xsoY7xrNNXuV4t1CSiyECFoJD1YMjw9fHwZejxzu4gu
gas_used:4020
gas_unit_price:100
sender:dcf462ef1bad8ed0901043126048acdbf6446f486eee2a38a12ddf8b727a2cc6
sequence_number:0
success:true
timestamp_us:1751426811613310
version:250249525
vm_status:Executed successfully
Follow the prompts: type yes
when asked for a Do you want to submit a transaction for a range of...
and press Enter
.
2. Use Go SDK to interact with contracts
Before you begin, please ensure that you have the Go language environment and VS Code installed on your system.
2.1 Install Go
Download Go: Visit the official Go download page, download and install the latest version of Go for your operating system.
Configure Environment Variables: The installer usually configures the environment variables automatically. If not, manually add the Go
bin
directory (e.g.,C:\Go\bin
or/usr/local/go/bin
) to your system'sPATH
environment variable.Verify Installation: Open a terminal or command prompt and enter the following command to verify that Go is installed correctly:
{path}\endless-orders>go version go version go1.24.4 windows/amd64
If you see the version number output, the installation was successful.
2.2 Install Visual Studio Code
Visit the official VS Code website to download and install the version suitable for your operating system.
2.2.1 Install the Go Extension
VS Code supports development in different languages through extensions. For Go, we need to install the official Go extension.
Open VS Code.
Click the Extensions icon in the sidebar or use the shortcut
Ctrl+Shift+X
.Enter
Go
in the search box.Find the official extension published by the Go Team at Google and click Install.

2.2..2 Install Go Development Tools
The Go extension relies on some command-line tools to provide advanced features like code completion, formatting, definition jumping, and debugging (e.g., gopls
, dlv
).
After installing the Go extension, a notification will usually appear in the bottom right corner suggesting you install these dependency tools. Click Install All.
If you miss the notification, you can also install them manually:
Open the Command Palette:
Ctrl+Shift+P
(Windows/Linux) orCmd+Shift+P
(macOS).Type
Go: Install/Update Tools
and press Enter.Check all the tools in the list, then click OK.
VS Code will automatically execute the
go install
command in the terminal to install these tools. Please ensure your network can access Go's domains.
2.3 Create Your Go Project
2.3.1 Initialize a Go Module
Since Go 1.11, Go Modules are the official way to manage project dependencies. Run the following command in the project root directory to initialize a module:
# Replace "endless-orders" with your module path, which is usually your code repository address
{path}\endless-orders>go mod init endless-orders
go: creating new go.mod: module endless-orders
After execution, a go.mod
file will be generated in the directory.
2.3.2 Create the main.go
File
Create a file named main.go
in the project root directory and enter the following "Hello, World!" code:
package main
import "fmt"
func main() {
fmt.Println("Hello, Endless!")
}
2.3.3 Add endless-go-sdk and cobra
In order to call the endless on-chain contract and conveniently process command line instructions, we need to add dependencies endless-go-sdk and cobra.
go get -u github.com/endless-labs/endless-go-sdk
To facilitate the processing of command line commands, we added cobra
package.
go get -u github.com/spf13/cobra
2.3.4 Create project structure directories and files
endless-orders
│─main.go
│
├─cmd
│ │─ order.go
│ │─ root.go
│
└─web3
│─ web3.go
main.go: program entry root.go: root Command order.go: All cli commands and parameter definitions and parsing of each command web3.go: All commands and interactions with on-chain contracts
2.3.5 Register root command
Definition a rootCmd in cmd/root.go
package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
)
var rootCmd = &cobra.Command{
Use: "order-cli",
Short: "A CLI to interact with the order_platform::orders Move contract",
Long: `A command-line interface to create, manage, and query orders on the Endless blockchain.`,
CompletionOptions: cobra.CompletionOptions{DisableDefaultCmd: true},
}
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Fprintf(os.Stderr, "Whoops. There was an error while executing your CLI '%s'", err)
os.Exit(1)
}
}
Then we can call its Execute() function in main.go as as follows
package main
import "endless-orders/cmd"
func main() {
cmd.Execute()
}
2.3.6 Create an account and faucet EDS on testnet
2.3.6.1 Create an account
An account is essentially a public-private key pair and an account address derived from them. We save the generated private key and account address locally, so that when needed, we can directly read the file and construct an account to interact with the chain.
1 Define and register the
Create account
command In cmd/order.go define and register the command, they call the corresponding specific implementation in web3/web3.go to complete the entire function.
// order.go
package cmd
import (
"endless-orders/web3"
"fmt"
"strconv"
"github.com/spf13/cobra"
)
// Create Account Command
var createAccountCmd = &cobra.Command{
Use: "create_account [account-name]",
Short: "Creates a new account",
Long: `Creates a new account and saves it locally.`,
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
accountName := args[0]
web3.CreateAccount(accountName)
},
}
func init() {
// Add the order command to the root command
rootCmd.AddCommand(createAccountCmd)
}
2 Implement the
Create account
command
// web3.go
package web3
import (
"encoding/hex"
"encoding/json"
"fmt"
"math/big"
"os"
"sync"
"github.com/endless-labs/endless-go-sdk"
"github.com/endless-labs/endless-go-sdk/bcs"
"github.com/endless-labs/endless-go-sdk/crypto"
)
// AccountData holds the information for a saved account
type AccountData struct {
PrivateKey string `json:"private_key"`
Address string `json:"address"`
}
func CreateAccount(accountName string) {
// Create a new Ed25519 account
account, err := endless.NewEd25519Account()
if err != nil {
panic("Failed to create account: " + err.Error())
}
// Save the account to a file
privateKeyBytes := account.Signer.(*crypto.Ed25519PrivateKey).Bytes()
data := AccountData{
PrivateKey: hex.EncodeToString(privateKeyBytes),
Address: account.Address.String(),
}
fileContent, err := json.MarshalIndent(data, "", " ")
if err != nil {
panic("Failed to marshal account data: " + err.Error())
}
err = os.WriteFile(accountName+".json", fileContent, 0644)
if err != nil {
panic("Failed to save account file: " + err.Error())
}
fmt.Printf("Account '%s' created.\n", accountName)
fmt.Printf("Address: %s\n", account.Address.String())
fmt.Printf("Saved to %s.json\n", accountName)
}
In this way, we have implemented a function to create an account and save it.
3 Create an account named alice
{path}\endless-orders>go build
{path}\endless-orders>endless-orders.exe create_account alice
Account 'alice' created.
Address: GVFJPNkqkdH9hx5CwFGnFPUFzbDUaBjdCB3U8WkKrce3
Saved to alice.json
2.3.6.2 faucet EDS on testnet for alice
1 Define and register the
Faucet Account
command Add the following code to the cmd/order.go
// Faucet Account Command
var faucetAccountCmd = &cobra.Command{
Use: "faucet_account [account-name]",
Short: "Funds an account from the faucet",
Long: `Requests funds from the faucet for a given account.`,
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
accountName := args[0]
web3.FaucetAccount(accountName)
},
}
Add faucetAccountCmd to init function.
// Add the order command to the root command
rootCmd.AddCommand(createAccountCmd)
rootCmd.AddCommand(faucetAccountCmd)
2 Implement the
Faucet account
command In order to easy for loading of an account, we implement a function in web3/web3.go
func LoadAccount(accountName string) *endless.Account {
// Load the account from the file
fileContent, err := os.ReadFile(accountName + ".json")
if err != nil {
panic("Failed to read account file: " + err.Error())
}
var data AccountData
err = json.Unmarshal(fileContent, &data)
if err != nil {
panic("Failed to unmarshal account data: " + err.Error())
}
privateKeyBytes, err := hex.DecodeString(data.PrivateKey)
if err != nil {
panic("Failed to decode private key: " + err.Error())
}
privateKey := &crypto.Ed25519PrivateKey{}
err = privateKey.FromBytes(privateKeyBytes)
if err != nil {
panic("privateKey key is not valid")
}
account, err := endless.NewAccountFromSigner(privateKey)
if err != nil {
panic("NewAccountFromSigner is not valid")
}
return account
}
To interact with the blockchain, you need to build an endless.Client
object. The endless.Client provides a Faucet function, which can directly get a EDS on the test network. To send a transaction, you need to pass in the SequenceNumber of the account. The new account does not exist on the chain and has no SequenceNumber. Therefore, err = client.Faucet(*account) will directly report an error. In this case, you need to set the SequenceNumber of the account to 0.
func FaucetAccount(accountName string) {
// Load the account from the file
account := LoadAccount(accountName)
// Create a client for Endless
client, err := endless.NewClient(endless.TestnetConfig)
if err != nil {
panic("Failed to create client:" + err.Error())
}
// Fund the account from the faucet
// err = client.Faucet(*account, endless.SequenceNumber(0)) // Use the sequence number to skip fetching it
// Use the sequence number to skip fetching it
err = client.Faucet(*account)
if err != nil {
pre_err := err
err = client.Faucet(*account, endless.SequenceNumber(0))
if err != nil {
panic("Failed to fund account:" + pre_err.Error())
}
}
Balance, err := client.AccountEDSBalance(account.Address)
if err != nil {
panic("Failed to get account balance:" + err.Error())
}
fmt.Printf("Successfully funded account '%s' from the faucet '%s'.\n", accountName, Balance)
}
At this point, all the functions of Faucet account
are completed
3 Faucet EDS on testnet for alice
{path}\endless-orders>go build
{path}\endless-orders>endless-orders.exe faucet_account alice
Successfully funded account 'alice' from the faucet '1000000000'.
2.3.7 Call the function of the published contract
So far, we have not interacted with the contract we published. Now let's create an order using our contract.
2.3.7.1 Create order subcommand
We put all interactive commands with the orders contract to the order subcommand. First define a orderCmd in cmd/order.go
var orderCmd = &cobra.Command{
Use: "order",
Short: "Manage orders",
Long: `The main command to manage orders on the order platform.`,
}
Then register orderCmd to rootCmd
func init() {
// Add the order command to the root command
rootCmd.AddCommand(orderCmd)
rootCmd.AddCommand(createAccountCmd)
rootCmd.AddCommand(faucetAccountCmd)
}
2.3.7.2 Implement Create Order Command for order subcommand
1 Define and register
createOrderCmd
fororderCmd
in cmd/order.go
// Create Order Command
var createOrderCmd = &cobra.Command{
Use: "create",
Short: "Creates a new order",
Long: `Creates a new order with the status PENDING_PAYMENT.`,
Run: func(cmd *cobra.Command, args []string) {
buyerName, _ := cmd.Flags().GetString("buyer")
sellerName, _ := cmd.Flags().GetString("seller-name")
itemId, _ := cmd.Flags().GetString("item-id")
quantity, _ := cmd.Flags().GetUint64("quantity")
unitPrice, _ := cmd.Flags().GetUint64("unit-price")
web3.CreateOrder(buyerName, sellerName, itemId, quantity, unitPrice)
},
}
func init() {
// Add subcommands to the order command
orderCmd.AddCommand(createOrderCmd)
// Add flags for the create command
createOrderCmd.Flags().String("buyer", "", "Address of the buyer (signer)")
createOrderCmd.Flags().String("seller-name", "", "Address of the seller")
createOrderCmd.Flags().String("item-id", "", "ID of the item being ordered")
createOrderCmd.Flags().Uint64("quantity", 0, "Quantity of the item to order")
createOrderCmd.Flags().Uint64("unit-price", 0, "Price per unit of the item")
createOrderCmd.MarkFlagRequired("buyer")
createOrderCmd.MarkFlagRequired("seller-name")
createOrderCmd.MarkFlagRequired("item-id")
createOrderCmd.MarkFlagRequired("quantity")
createOrderCmd.MarkFlagRequired("unit-price")
// Add the order command to the root command
rootCmd.AddCommand(orderCmd)
rootCmd.AddCommand(createAccountCmd)
rootCmd.AddCommand(faucetAccountCmd)
}
2 Define contract address and module address In endless, one address can publish multiple contracts, and each contract can be called a module. Such as 0x4 address is EndlessToken package. It contains Six modules, including
coin
,collection
,nft
,property_map
,royalty
andtoken
. EndlessToken package
Define endless-orders
address and orders
module in web3/web3.go.
func GetContractAddress() *endless.AccountAddress {
once.Do(func() {
a := &endless.AccountAddress{}
addrErr = a.ParseStringRelaxed("FsWq9ZonkCHLZfoRG3Ci8PGr7ps3Mo5mqLGyE1CyRNhb")
if addrErr == nil {
addr = a
} else {
panic("GetContractAddress Faild.")
}
})
return addr
}
var CONTRACT_MODULE = "orders"
Use GetContractAddress
to get the contract address
3 Implement
createOrderCmd
Serialize Arguments: The function's arguments (quantity, unitPrice, itemId) are serialized into the BCS (Binary Canonical Serialization) format, which is required by the Endless blockchain.
quantity and unitPrice are converted to u128.
itemId is serialized as a string.
Construct Entry Function Payload: It builds an endless.EntryFunction struct. This struct specifies the target smart contract to call,
Module: The contract's on-chain address (retrieved via GetContractAddress) and the module name (orders).
Function: The name of the function to call (create_order).
Args: The serialized arguments for the function call: seller's address, item ID, quantity, and unit price.
func CreateOrder(buyerName, sellerName, itemId string, quantity, unitPrice uint64) {
buyer := LoadAccount(buyerName)
seller := LoadAccount(sellerName)
fmt.Printf("Creating order for buyer: %s seller:%s\n", buyer.Address.String(), seller.Address.String())
quantity_u128, err := bcs.SerializeU128(*big.NewInt(int64(quantity)))
if err != nil {
panic("quantity format error.")
}
unitPrice_u128, err := bcs.SerializeU128(*big.NewInt(int64(unitPrice)))
if err != nil {
panic("quantity format error.")
}
itemId_bytes, err := bcs.SerializeSingle(func(ser *bcs.Serializer) {
ser.WriteString(itemId)
})
if err != nil {
panic("failed to serialize itemId.")
}
entryFunction := endless.EntryFunction{
Module: endless.ModuleId{
Address: *GetContractAddress(),
Name: CONTRACT_MODULE,
},
Function: "create_order",
ArgTypes: []endless.TypeTag{},
Args: [][]byte{
seller.Address[:],
itemId_bytes,
quantity_u128,
unitPrice_u128,
},
}
client, err := endless.NewClient(endless.TestnetConfig)
if err != nil {
panic("Failed to create client:" + err.Error())
}
rawTxn, err := client.BuildTransaction(
buyer.AccountAddress(),
endless.TransactionPayload{
Payload: &entryFunction,
},
)
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, buyer)
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)
if !simulationResult[0].Success {
panic("Simulate transaction error.")
}
// 3. Sign transaction
signedTxn, err := rawTxn.SignedTransaction(buyer)
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
fmt.Printf("txnHash: %s\n", txnHash)
// 5. Wait for the transaction to complete
userTransaction, err := client.WaitForTransaction(txnHash)
if err != nil {
panic("Failed to wait for transaction:" + err.Error())
}
if !userTransaction.Success {
panic("Failed to on chain success:" + userTransaction.VmStatus)
}
}
In this way, we have completed the function of creating orders on the chain.
4 Create an order on chain
{path}\endless-orders>go build
{path}\endless-orders>endless-orders.exe order create --buyer alice --seller-name bob --item-id "items-00001" --quantity 100 --unit-price 100000
Creating order for buyer: GVFJPNkqkdH9hx5CwFGnFPUFzbDUaBjdCB3U8WkKrce3 seller:C6nCccsGQ6A6JqoGPS8S7n8xA7YRphsibp2Ba1yZNk2f
================ Simulation ================
Gas unit price: 100
Gas used: 475
Total gas fee: 47500
Status: Executed successfully
txnHash: 0xcc8e12ce5a32ce1d0384254ac7ef44cfae3e241e4b2cf2802fa7cd88060e7962
Visit the Official Endless Scan Website,can find the event orders::OrderCreatedEvent
,or you can Parse the UserTransaction returned by WaitForTransaction to extract this event. We can know the newly created order id is 1.
// FsWq9ZonkCHLZfoRG3Ci8PGr7ps3Mo5mqLGyE1CyRNhb::orders::OrderCreatedEvent
{
"buyer": "GVFJPNkqkdH9hx5CwFGnFPUFzbDUaBjdCB3U8WkKrce3",
"order_id": "1",
"seller": "C6nCccsGQ6A6JqoGPS8S7n8xA7YRphsibp2Ba1yZNk2f",
"total_price": "10000000"
}
2.3.7.3 Implementing Other Order Subcommands
Similar to the order creation process described in 2.3.7.2, you can implement other commands other order commands such as order payment, order shipping, etc., The complete functional implementation is already in cmd/order.go and web3/web3.go in the latest code repository. It is important to note that when Go language json parses the field type of the returned object, sometimes the type it parses is not the type you expected. That is why when calling the view function get_order_status, its return value is converted to float64 in Go. For example, when calling the get_order_status view function, its return value is treated as a float64 in Go.
Last updated