Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion relayer/client/mocks/mock_ptb_client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 39 additions & 4 deletions relayer/client/ptb_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ type SuiPTBClient interface {
QueryTransactions(ctx context.Context, fromAddress string, cursor *string, limit *uint64) (models.SuiXQueryTransactionBlocksResponse, error)
GetTransactionStatus(ctx context.Context, digest string) (TransactionResult, error)
GetCoinsByAddress(ctx context.Context, address string) ([]models.CoinData, error)
QueryCoinsByAddress(ctx context.Context, address string, coinType string) ([]models.CoinData, error)
EstimateGas(ctx context.Context, txBytes string) (uint64, error)
GetReferenceGasPrice(ctx context.Context) (*big.Int, error)
FinishPTBAndSend(ctx context.Context, txnSigner *signer.Signer, tx *transaction.Transaction, requestType TransactionRequestType) (SuiTransactionBlockResponse, error)
Expand Down Expand Up @@ -719,13 +720,47 @@ func (c *PTBClient) GetCoinsByAddress(ctx context.Context, address string) ([]mo
Owner: address,
Limit: uint64(maxCoinsPageSize),
}
hasNextPage := true

response, err := c.client.SuiXGetAllCoins(ctx, coinsReq)
if err != nil {
return fmt.Errorf("failed to get coins: %w", err)
for hasNextPage {
response, err := c.client.SuiXGetAllCoins(ctx, coinsReq)
if err != nil {
return fmt.Errorf("failed to get coins: %w", err)
}

result = append(result, response.Data...)

hasNextPage = response.HasNextPage
coinsReq.Cursor = response.NextCursor
}

result = response.Data
return nil
})

return result, err
}

func (c *PTBClient) QueryCoinsByAddress(ctx context.Context, address string, coinType string) ([]models.CoinData, error) {
var result []models.CoinData
err := c.WithRateLimit(ctx, "QueryCoinsByAddress", func(ctx context.Context) error {
coinsReq := models.SuiXGetCoinsRequest{
Owner: address,
CoinType: coinType,
Limit: uint64(maxCoinsPageSize),
}
hasNextPage := true

for hasNextPage {
response, err := c.client.SuiXGetCoins(ctx, coinsReq)
if err != nil {
return fmt.Errorf("failed to get coins: %w", err)
}

result = append(result, response.Data...)

hasNextPage = response.HasNextPage
coinsReq.Cursor = response.NextCursor
}

return nil
})
Expand Down
39 changes: 39 additions & 0 deletions relayer/client/ptb_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,45 @@ func TestPTBClient(t *testing.T) {
require.NoError(t, err)
require.Equal(t, latestPackageId, packageId)
})

t.Run("QueryCoinsByAddress", func(t *testing.T) {
// Create and send random coins to the account address for testing
// This ensures we have coins to query
coinAmount := uint64(1000000) // 1 SUI

// Create a coin transfer transaction to send SUI to the account
transferReq := client.MoveCallRequest{
Signer: accountAddress,
PackageObjectId: "0x2",
Module: "pay",
Function: "split_and_transfer",
Arguments: []any{coinAmount, accountAddress},
GasBudget: 1000000000,
}

// Execute the coin transfer
txnMetadata, err := relayerClient.MoveCall(context.Background(), transferReq)
if err == nil && txnMetadata.TxBytes != "" {
_, err = relayerClient.SignAndSendTransaction(
context.Background(),
txnMetadata.TxBytes,
publicKeyBytes,
"WaitForLocalExecution",
)
// Ignore errors as this is just setup for the test
}

coins, err := relayerClient.QueryCoinsByAddress(context.Background(), accountAddress, "0x2::sui::SUI")
require.NoError(t, err)
require.NotNil(t, coins)

require.True(t, len(coins) > 0)
for _, coin := range coins {
require.Equal(t, "0x2::sui::SUI", coin.CoinType)
}

utils.PrettyPrint(coins)
})
}

func IncrementCounterWithMoveCall(t *testing.T, relayerClient *client.PTBClient, packageId string, counterObjectId string, accountAddress string, signerPublicKey []byte) string {
Expand Down
8 changes: 8 additions & 0 deletions relayer/testutils/fake_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ func (c *FakeSuiPTBClient) GetReferenceGasPrice(ctx context.Context) (*big.Int,
return big.NewInt(1000), nil
}

func (c *FakeSuiPTBClient) QueryCoinsByAddress(ctx context.Context, address string, coinType string) ([]models.CoinData, error) {
return []models.CoinData{}, nil
}

// StatefulFakeSuiPTBClient is a more sophisticated fake client that can change behavior
// based on gas budget and track call counts for testing gas bump scenarios
type StatefulFakeSuiPTBClient struct {
Expand Down Expand Up @@ -338,3 +342,7 @@ func (c *StatefulFakeSuiPTBClient) GetCCIPPackageID(ctx context.Context, offRamp
func (c *StatefulFakeSuiPTBClient) GetReferenceGasPrice(ctx context.Context) (*big.Int, error) {
return big.NewInt(1000), nil
}

func (c *StatefulFakeSuiPTBClient) QueryCoinsByAddress(ctx context.Context, address string, coinType string) ([]models.CoinData, error) {
return []models.CoinData{}, nil
}
Loading