Skip to content

Commit

Permalink
Merge pull request #50 from mirrorworld-universe/aide
Browse files Browse the repository at this point in the history
feat: Add fee settlement functionality and update configuration for S…
  • Loading branch information
ZeneDeLuca authored Jan 17, 2025
2 parents 4e25d43 + ff8fb69 commit 7b793ee
Show file tree
Hide file tree
Showing 4 changed files with 263 additions and 0 deletions.
3 changes: 3 additions & 0 deletions hypergrid-aide/.hypergrid-aide.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ solana:
baselayer_rpc: https://api.testnet.solana.com
private_key: ~/.config/solana/id.json
inbox_program_id: FG8P631H9q5b53qsVM9aD71GZTWBKvujtqeWUGstpeka
sonic_grid_rpc: http://api.grid-sonic.sonic.game
fee_program_id: SonicFeeSet1ement11111111111111111111111111
fee_data_account_id: SonicFeeSet1ementData1111111111111111111112
cosmos:
rpc: https://api.testnet.hssn.sonic.game/
address_prefix: cosmos
Expand Down
73 changes: 73 additions & 0 deletions hypergrid-aide/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"encoding/json"
"fmt"
"io"
"log"
Expand All @@ -21,8 +22,11 @@ import (
// Default values for the global variables
var SOLANA_RPC_ENDPOINT = "http://localhost:8899"
var SOLANA_BASELAYER_RPC = "https://api.testnet.solana.com"
var SOLANA_SONIC_GRID_RPC = "http://api.grid-sonic.sonic.game"
var SOLANA_PRIVATE_KEY = "~/.config/solana/id.json"
var SOLANA_InboxProgramID = "FG8P631H9q5b53qsVM9aD71GZTWBKvujtqeWUGstpeka"
var SonicFeeProgramID = "SonicFeeSet1ement11111111111111111111111111"
var SonicFeeDataAccountID = "SonicFeeSet1ementData1111111111111111111112"
var COSMOS_RPC_ENDPOINT = "http://localhost:26657"
var COSMOS_ADDRESS_PREFIX = "cosmos"
var COSMOS_HOME = "~/.hypergrid-ssn"
Expand Down Expand Up @@ -78,6 +82,9 @@ func readVariablesFromYaml(filename string) {
SOLANA_BASELAYER_RPC = solana_params["baselayer_rpc"].(string)
SOLANA_PRIVATE_KEY = solana_params["private_key"].(string)
SOLANA_InboxProgramID = solana_params["inbox_program_id"].(string)
SOLANA_SONIC_GRID_RPC = solana_params["sonic_grid_rpc"].(string)
SonicFeeProgramID = solana_params["fee_program_id"].(string)
SonicFeeDataAccountID = solana_params["fee_data_account_id"].(string)

cosmos_params := params["cosmos"].(map[string]interface{})
COSMOS_RPC_ENDPOINT = cosmos_params["rpc"].(string)
Expand Down Expand Up @@ -163,6 +170,60 @@ func SyncStateAccount(cosmos tools.CosmosClient, account cosmosaccount.Account,
log.Println(res)
}

func SettleFeeBill(cosmos tools.CosmosClient, account cosmosaccount.Account) {
fromId := uint64(0)
endId := uint64(0)

res1, err1 := cosmos.QueryLastFeeSettlementBill()
if err1 != nil {
log.Fatal(err1)
}
if len(res1.FeeSettlementBill) > 0 {
// Id = res1.FeeSettlementBill[0].Id
fromId = res1.FeeSettlementBill[0].EndId
}

res2, err2 := cosmos.QueryLastGridBlockFee()
if err2 != nil {
log.Fatal(err1)
}
if len(res2.GridBlockFee) > 0 {
// Id = res1.FeeSettlementBill[0].Id
endId = res2.GridBlockFee[0].Id
}

if fromId == 0 && endId == 0 {
log.Fatal("fromId or endId is 0")
return
}

res, err := cosmos.SettleFeeBill(account, fromId, endId)
if err != nil {
log.Fatal(err)
}
log.Print("SettleFeeBill:\n\n")
log.Println(res)

res3, err3 := cosmos.QueryLastFeeSettlementBill()
if err3 != nil {
log.Fatal(err3)
}

bills := res3.FeeSettlementBill[0].Bill
//convert bills to bytes
// billsBytes := []byte(bills)
var Bills map[string]uint64
json.Unmarshal([]byte(bills), &Bills)

res4, err4 := tools.SendTxFeeSettlement(SOLANA_PRIVATE_KEY, SOLANA_SONIC_GRID_RPC, SonicFeeProgramID, SonicFeeDataAccountID, res3.FeeSettlementBill[0].FromId, res3.FeeSettlementBill[0].EndId, Bills)
if err4 != nil {
log.Fatal(err4)
}

log.Print("SendTxFeeSettlement:\n\n")
log.Println(res4)
}

func main() {
log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
//get program arguments
Expand Down Expand Up @@ -238,6 +299,18 @@ func main() {
}
SendGridBlockFees(*cosmos, *solana, account, gridId, limit)
// break
case "settle":
cosmos := tools.NewCosmosClient(
cosmosclient.WithNodeAddress(COSMOS_RPC_ENDPOINT),
cosmosclient.WithAddressPrefix(COSMOS_ADDRESS_PREFIX),
cosmosclient.WithHome(COSMOS_HOME),
cosmosclient.WithGas(strconv.FormatUint(COSMOS_GAS, 10)),
)
account, err := cosmos.Account(COSMOS_KEY)
if err != nil {
log.Fatal(err)
}
SettleFeeBill(*cosmos, account)
default:
fmt.Println("Usage: hypergrid-aide <command>")
}
Expand Down
96 changes: 96 additions & 0 deletions hypergrid-aide/tools/cosmos.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strconv"

// Importing the general purpose Cosmos blockchain client
"github.com/cosmos/cosmos-sdk/types/query"
"github.com/ignite/cli/v28/ignite/pkg/cosmosaccount"
"github.com/ignite/cli/v28/ignite/pkg/cosmosclient"
// Importing the types package of your blog blockchain
Expand Down Expand Up @@ -156,6 +157,28 @@ func (c *CosmosClient) QueryAllGridBlockFees() (*types.QueryAllGridBlockFeeRespo
return queryResp, err
}

func (c *CosmosClient) QueryLastGridBlockFee() (*types.QueryAllGridBlockFeeResponse, error) {
// Instantiate a query client for your `blog` blockchain
queryClient := types.NewQueryClient(c.Client.Context())

// Query the blockchain using the client's `PostAll` method
// to get all posts store all posts in queryResp
// return queryClient.GridBlockFeeAll(c.Context, &types.QueryAllGridBlockFeeRequest{})
queryResp, err := queryClient.GridBlockFeeAll(c.Context, &types.QueryAllGridBlockFeeRequest{Pagination: &query.PageRequest{
Limit: 1,
Reverse: true,
}})
if err != nil {
log.Fatal(err)
return nil, err
}

// Print response from querying all the posts
log.Print("\n\nAll grid tx fee:\n\n")
log.Println(queryResp)
return queryResp, err
}

func (c *CosmosClient) QueryGridBlockFee(_id uint64) (*types.QueryGetGridBlockFeeResponse, error) {
// Instantiate a query client for your `blog` blockchain
queryClient := types.NewQueryClient(c.Client.Context())
Expand Down Expand Up @@ -190,3 +213,76 @@ func (c *CosmosClient) QueryAllHypergridNodes() (*types.QueryAllHypergridNodeRes
log.Println(queryResp)
return queryResp, err
}

func (c *CosmosClient) SettleFeeBill(account cosmosaccount.Account, fromId uint64, endId uint64) (*cosmosclient.Response, error) {
address, err := account.Address(COSMOS_ADDRESS_PREFIX)
if err != nil {
log.Fatal(err)
}
log.Println("Account: ", address)

// Define a message to create a grid inbox
msg := types.MsgCreateFeeSettlementBill{
Creator: address,
FromId: fromId,
EndId: endId,
}

// Broadcast a transaction from account with the message
// to create a post store response in txResp
txResp, err := c.Client.BroadcastTx(c.Context, account, &msg)
if err != nil {
log.Fatal(err)
return nil, err
}
// Print response from broadcasting a transaction
log.Print("MsgCreateFeeSettlementBill:\n\n")
log.Println(txResp)

_, err1 := c.Client.WaitForTx(c.Context, txResp.TxHash)
if err1 != nil {
log.Fatal(err1)
return nil, err1
}

return &txResp, nil
}

func (c *CosmosClient) QueryLastFeeSettlementBill() (*types.QueryAllFeeSettlementBillResponse, error) {
// Instantiate a query client for your `blog` blockchain
queryClient := types.NewQueryClient(c.Client.Context())

// Query the blockchain using the client's `PostAll` method
// to get all posts store all posts in queryResp
queryResp, err := queryClient.FeeSettlementBillAll(c.Context, &types.QueryAllFeeSettlementBillRequest{Pagination: &query.PageRequest{
Limit: 1,
Reverse: true,
}})
if err != nil {
log.Fatal(err)
return nil, err
}

// Print response from querying all the posts
log.Print("\n\nAll grid tx fee:\n\n")
log.Println(queryResp)
return queryResp, err
}

func (c *CosmosClient) QueryGetFeeSettlementBill(_id uint64) (*types.QueryGetFeeSettlementBillResponse, error) {
// Instantiate a query client for your `blog` blockchain
queryClient := types.NewQueryClient(c.Client.Context())

// Query the blockchain using the client's `PostAll` method
// to get all posts store all posts in queryResp
queryResp, err := queryClient.FeeSettlementBill(c.Context, &types.QueryGetFeeSettlementBillRequest{Id: _id})
if err != nil {
log.Fatal(err)
return nil, err
}

// Print response from querying all the posts
log.Print("\n\nGet grid tx fee:\n\n")
log.Println(queryResp)
return queryResp, err
}
91 changes: 91 additions & 0 deletions hypergrid-aide/tools/solana.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package tools

import (
"bytes"
"context"
"crypto/sha256"
"encoding/binary"
"encoding/hex"
"fmt"
"log"
"sort"
"strings"

"github.com/davecgh/go-spew/spew"
Expand Down Expand Up @@ -371,3 +374,91 @@ func SendTxInbox(localPrivateKey string, rpcUrl string, programId string, slot u

return sig, nil
}

type SettlementBillParam struct {
Key solana.PublicKey
Amount uint64
}

type SettleFeeBillParams struct {
Instruction uint32
FromID uint64
EndID uint64
Bills []SettlementBillParam
}

// BorshEncode encodes the InstructionData using Borsh
func (d *SettleFeeBillParams) BorshEncode() ([]byte, error) {
buf := new(bytes.Buffer)
err := binary.Write(buf, binary.LittleEndian, d.Instruction)
if err != nil {
return nil, err
}
err = binary.Write(buf, binary.LittleEndian, d.FromID)
if err != nil {
return nil, err
}
err = binary.Write(buf, binary.LittleEndian, d.EndID)
if err != nil {
return nil, err
}
billCount := uint64(len(d.Bills))
err = binary.Write(buf, binary.LittleEndian, billCount)
if err != nil {
return nil, err
}
for _, bill := range d.Bills {
err = binary.Write(buf, binary.LittleEndian, bill.Key[:])
if err != nil {
return nil, err
}
err = binary.Write(buf, binary.LittleEndian, bill.Amount)
if err != nil {
return nil, err
}
}
return buf.Bytes(), nil
}

func SendTxFeeSettlement(localPrivateKey string, rpcUrl string, SonicFeeProgramID string, SonicFeeDataAccountID string, FromId uint64, EndID uint64, bills map[string]uint64) (*solana.Signature, error) {
Bills := []SettlementBillParam{}
// convert bills to []SettlementBillParam
for key, value := range bills {
Bills = append(Bills, SettlementBillParam{
Key: solana.MustPublicKeyFromBase58(key),
Amount: value,
})
}

//sort bills by key
sort.Slice(Bills, func(i, j int) bool {
return Bills[i].Key.String() < Bills[j].Key.String()
})

instructionData := SettleFeeBillParams{
Instruction: 1,
FromID: FromId,
EndID: EndID,
Bills: Bills,
}

// Serialize to bytes using Borsh
serializedData, err := instructionData.BorshEncode() // borsh.Serialize(instructionData)
if err != nil {
// panic(err)
return nil, err
}

accounts := solana.AccountMetaSlice{
solana.NewAccountMeta(solana.MustPublicKeyFromBase58(SonicFeeDataAccountID), true, false),
}

signer, err := getLocalPrivateKey(localPrivateKey)
if err != nil {
// panic(err)
return nil, err
}

signers := []solana.PrivateKey{signer}
return sendSonicTx(rpcUrl, SonicFeeProgramID, accounts, serializedData, signers)
}

0 comments on commit 7b793ee

Please sign in to comment.