Skip to content

Commit

Permalink
Merge pull request #151 from InjectiveLabs/feat/order_hash_generation…
Browse files Browse the repository at this point in the history
…_for_multi_subaccount

feat/order_hash_generation_for_multi_subaccount
  • Loading branch information
aarmoa authored Sep 11, 2023
2 parents d4d5104 + fe7fb94 commit 986e2b0
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 9 deletions.
14 changes: 12 additions & 2 deletions client/chain/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,14 @@ type ChainClient interface {
) *authztypes.MsgGrant

DefaultSubaccount(acc cosmtypes.AccAddress) eth.Hash
Subaccount(account cosmtypes.AccAddress, index int) eth.Hash

GetSubAccountNonce(ctx context.Context, subaccountId eth.Hash) (*exchangetypes.QuerySubaccountTradeNonceResponse, error)
GetFeeDiscountInfo(ctx context.Context, account string) (*exchangetypes.QueryFeeDiscountAccountInfoResponse, error)

UpdateSubaccountNonceFromChain() error
ComputeOrderHashes(spotOrders []exchangetypes.SpotOrder, derivativeOrders []exchangetypes.DerivativeOrder) (OrderHashes, error)
SynchronizeSubaccountNonce(subaccountId eth.Hash) error
ComputeOrderHashes(spotOrders []exchangetypes.SpotOrder, derivativeOrders []exchangetypes.DerivativeOrder, subaccountId eth.Hash) (OrderHashes, error)

SpotOrder(defaultSubaccountID eth.Hash, network common.Network, d *SpotOrderData) *exchangetypes.SpotOrder
DerivativeOrder(defaultSubaccountID eth.Hash, network common.Network, d *DerivativeOrderData) *exchangetypes.DerivativeOrder
Expand Down Expand Up @@ -938,7 +940,15 @@ func (c *chainClient) GetGasFee() (string, error) {
}

func (c *chainClient) DefaultSubaccount(acc cosmtypes.AccAddress) eth.Hash {
return eth.BytesToHash(eth.RightPadBytes(acc.Bytes(), 32))
return c.Subaccount(acc, 0)
}

func (c *chainClient) Subaccount(account cosmtypes.AccAddress, index int) eth.Hash {
ethAddress := eth.BytesToAddress(account.Bytes())
ethLowerAddress := strings.ToLower(ethAddress.String())

subaccountId := fmt.Sprintf("%s%024x", ethLowerAddress, index)
return eth.HexToHash(subaccountId)
}

func (c *chainClient) GetSubAccountNonce(ctx context.Context, subaccountId eth.Hash) (*exchangetypes.QuerySubaccountTradeNonceResponse, error) {
Expand Down
104 changes: 104 additions & 0 deletions client/chain/chain_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package chain

import (
"github.com/InjectiveLabs/sdk-go/client/common"
rpchttp "github.com/cometbft/cometbft/rpc/client/http"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
cosmtypes "github.com/cosmos/cosmos-sdk/types"
eth "github.com/ethereum/go-ethereum/common"
"os"
"testing"
)

func accountForTests() (cosmtypes.AccAddress, keyring.Keyring, error) {
senderAddress, cosmosKeyring, err := InitCosmosKeyring(
os.Getenv("HOME")+"/.injectived",
"injectived",
"file",
"inj-user",
"12345678",
"5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e", // keyring will be used if pk not provided
false,
)

return senderAddress, cosmosKeyring, err
}

func createClient(senderAddress cosmtypes.AccAddress, cosmosKeyring keyring.Keyring, network common.Network) (ChainClient, error) {
tmClient, _ := rpchttp.New(network.TmEndpoint, "/websocket")
clientCtx, err := NewClientContext(
network.ChainId,
senderAddress.String(),
cosmosKeyring,
)

if err != nil {
return nil, err
}

clientCtx = clientCtx.WithNodeURI(network.TmEndpoint).WithClient(tmClient)

chainClient, err := NewChainClient(
clientCtx,
network.ChainGrpcEndpoint,
common.OptionTLSCert(network.ChainTlsCert),
common.OptionGasPrices("500000000inj"),
)

return chainClient, err
}

func TestDefaultSubaccount(t *testing.T) {
network := common.LoadNetwork("testnet", "k8s")
senderAddress, cosmosKeyring, err := accountForTests()

if err != nil {
t.Errorf("Error creating the address %v", err)
}

chainClient, err := createClient(senderAddress, cosmosKeyring, network)

if err != nil {
t.Errorf("Error creating the client %v", err)
}

defaultSubaccountID := chainClient.DefaultSubaccount(senderAddress)

expectedSubaccountId := "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000"
expectedSubaccountIdHash := eth.HexToHash(expectedSubaccountId)
if defaultSubaccountID != expectedSubaccountIdHash {
t.Error("The default subaccount is calculated incorrectly")
}
}

func TestGetSubaccountWithIndes(t *testing.T) {
network := common.LoadNetwork("testnet", "k8s")
senderAddress, cosmosKeyring, err := accountForTests()

if err != nil {
t.Errorf("Error creating the address %v", err)
}

chainClient, err := createClient(senderAddress, cosmosKeyring, network)

if err != nil {
t.Errorf("Error creating the client %v", err)
}

subaccountOne := chainClient.Subaccount(senderAddress, 1)
subaccountThirty := chainClient.Subaccount(senderAddress, 30)

expectedSubaccounOnetId := "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000001"
expectedSubaccountOneIdHash := eth.HexToHash(expectedSubaccounOnetId)

expectedSubaccounThirtytId := "0xaf79152ac5df276d9a8e1e2e22822f971347490200000000000000000000001e"
expectedSubaccountThirtyIdHash := eth.HexToHash(expectedSubaccounThirtytId)

if subaccountOne != expectedSubaccountOneIdHash {
t.Error("The subaccount with index 1 was calculated incorrectly")
}
if subaccountThirty != expectedSubaccountThirtyIdHash {
t.Error("The subaccount with index 30 was calculated incorrectly")
}

}
17 changes: 12 additions & 5 deletions client/chain/orderhash.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,26 +58,33 @@ var domain = gethsigner.TypedDataDomain{
}

func (c *chainClient) UpdateSubaccountNonceFromChain() error {
subaccountId := c.DefaultSubaccount(c.ctx.FromAddress)
for subaccountId := range c.subaccountToNonce {
err := c.SynchronizeSubaccountNonce(subaccountId)
if err != nil {
return err
}
}
return nil
}

func (c *chainClient) SynchronizeSubaccountNonce(subaccountId common.Hash) error {
res, err := c.GetSubAccountNonce(context.Background(), subaccountId)
if err != nil {
return err
}

c.subaccountToNonce[subaccountId] = res.Nonce
return nil
}

func (c *chainClient) ComputeOrderHashes(spotOrders []exchangetypes.SpotOrder, derivativeOrders []exchangetypes.DerivativeOrder) (OrderHashes, error) {
func (c *chainClient) ComputeOrderHashes(spotOrders []exchangetypes.SpotOrder, derivativeOrders []exchangetypes.DerivativeOrder, subaccountId common.Hash) (OrderHashes, error) {
if len(spotOrders)+len(derivativeOrders) == 0 {
return OrderHashes{}, nil
}

orderHashes := OrderHashes{}
// get nonce
subaccountId := c.DefaultSubaccount(c.ctx.FromAddress)
if _, exist := c.subaccountToNonce[subaccountId]; !exist {
if err := c.UpdateSubaccountNonceFromChain(); err != nil {
if err := c.SynchronizeSubaccountNonce(subaccountId); err != nil {
return OrderHashes{}, err
}
}
Expand Down
4 changes: 2 additions & 2 deletions examples/chain/0_LocalOrderHash/example.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func main() {
}

// prepare tx msg
defaultSubaccountID := chainClient.DefaultSubaccount(senderAddress)
defaultSubaccountID := chainClient.Subaccount(senderAddress, 1)

spotOrder := chainClient.SpotOrder(defaultSubaccountID, network, &chainclient.SpotOrderData{
OrderType: exchangetypes.OrderType_BUY,
Expand Down Expand Up @@ -87,7 +87,7 @@ func main() {
msg1.Orders = []exchangetypes.DerivativeOrder{*derivativeOrder, *derivativeOrder}

// compute local order hashes
orderHashes, err := chainClient.ComputeOrderHashes(msg.Orders, msg1.Orders)
orderHashes, err := chainClient.ComputeOrderHashes(msg.Orders, msg1.Orders, defaultSubaccountID)

if err != nil {
fmt.Println(err)
Expand Down

0 comments on commit 986e2b0

Please sign in to comment.