Skip to content

Commit

Permalink
add test for transferring SOl from node
Browse files Browse the repository at this point in the history
  • Loading branch information
aalu1418 committed Sep 26, 2024
1 parent 8007501 commit f6d19a7
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 2 deletions.
11 changes: 9 additions & 2 deletions pkg/solana/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -561,8 +561,15 @@ func (c *chain) sendTx(ctx context.Context, from, to string, amount *big.Int, ba
}
}

txm := c.TxManager()
err = txm.Enqueue("", tx)
chainTxm := c.TxManager()
err = chainTxm.Enqueue("", tx,
txm.SetComputeUnitLimit(500), // reduce from default 200K limit - should only take 450 compute units
// no fee bumping and no additional fee - makes validating balance accurate
txm.SetComputeUnitPriceMax(0),
txm.SetComputeUnitPriceMin(0),
txm.SetBaseComputeUnitPrice(0),
txm.SetFeeBumpPeriod(0),
)
if err != nil {
return fmt.Errorf("transaction failed: %w", err)
}
Expand Down
73 changes: 73 additions & 0 deletions pkg/solana/chain_test.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
package solana

import (
"context"
"errors"
"fmt"
"io"
"math/big"
"net/http"
"net/http/httptest"
"strings"
"sync"
"testing"

"github.com/gagliardetto/solana-go"
"github.com/gagliardetto/solana-go/rpc"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"

"github.com/smartcontractkit/chainlink-common/pkg/config"
"github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink-common/pkg/utils/tests"

"github.com/smartcontractkit/chainlink-solana/pkg/solana/client"
solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config"
"github.com/smartcontractkit/chainlink-solana/pkg/solana/fees"
"github.com/smartcontractkit/chainlink-solana/pkg/solana/txm/mocks"
)

const TestSolanaGenesisHashTemplate = `{"jsonrpc":"2.0","result":"%s","id":1}`
Expand Down Expand Up @@ -238,3 +246,68 @@ func TestSolanaChain_VerifiedClient_ParallelClients(t *testing.T) {
func ptr[T any](t T) *T {
return &t
}

func TestChain_Transact(t *testing.T) {
ctx := tests.Context(t)
url := client.SetupLocalSolNode(t)
lgr, logs := logger.TestObserved(t, zapcore.DebugLevel)

// transaction parameters
sender, err := solana.NewRandomPrivateKey()
require.NoError(t, err)
receiver, err := solana.NewRandomPrivateKey()
require.NoError(t, err)
amount := big.NewInt(100_000_000_000 - 5_000) // total balance - tx fee
client.FundTestAccounts(t, solana.PublicKeySlice{sender.PublicKey()}, url)

// configuration
cfg := solcfg.NewDefault()
cfg.Nodes = append(cfg.Nodes, &solcfg.Node{
Name: ptr("localnet-" + t.Name()),
URL: config.MustParseURL(url),
SendOnly: false,
})

// mocked keystore
mkey := mocks.NewSimpleKeystore(t)
mkey.On("Sign", mock.Anything, sender.PublicKey().String(), mock.Anything).Return(func(_ context.Context, _ string, data []byte) []byte {
sig, _ := sender.Sign(data)
return sig[:]
}, nil)

c, err := newChain("localnet", cfg, mkey, lgr)
require.NoError(t, err)
require.NoError(t, c.txm.Start(ctx))

require.NoError(t, c.Transact(ctx, sender.PublicKey().String(), receiver.PublicKey().String(), amount, true))
tests.AssertLogEventually(t, logs, "tx state: confirmed")
tests.AssertLogEventually(t, logs, "stopped tx retry")
require.NoError(t, c.txm.Close())

filteredLogs := logs.FilterMessage("tx state: confirmed").All()
require.Len(t, filteredLogs, 1)
sig, ok := filteredLogs[0].ContextMap()["signature"]
require.True(t, ok)

// inspect transaction
solClient := rpc.New(url)
res, err := solClient.GetTransaction(ctx, solana.MustSignatureFromBase58(sig.(string)), &rpc.GetTransactionOpts{Commitment: "confirmed"})
require.NoError(t, err)
require.Nil(t, res.Meta.Err) // no error

// validate balances change as expected
require.Equal(t, amount.Uint64()+5_000, res.Meta.PreBalances[0])
require.Zero(t, res.Meta.PostBalances[0])
require.Zero(t, res.Meta.PreBalances[1])
require.Equal(t, amount.Uint64(), res.Meta.PostBalances[1])

tx, err := res.Transaction.GetTransaction()
require.NoError(t, err)
require.Len(t, tx.Message.Instructions, 3)
price, err := fees.ParseComputeUnitPrice(tx.Message.Instructions[0].Data)
require.NoError(t, err)
assert.Equal(t, fees.ComputeUnitPrice(0), price)
limit, err := fees.ParseComputeUnitLimit(tx.Message.Instructions[2].Data)
require.NoError(t, err)
assert.Equal(t, fees.ComputeUnitLimit(500), limit)
}
30 changes: 30 additions & 0 deletions pkg/solana/txm/mocks/simple_keystore.go

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

4 changes: 4 additions & 0 deletions pkg/solana/txm/txm.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/google/uuid"

"github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink-common/pkg/loop"
"github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink-common/pkg/utils"

Expand All @@ -32,8 +33,11 @@ var _ services.Service = (*Txm)(nil)
//go:generate mockery --name SimpleKeystore --output ./mocks/ --case=underscore --filename simple_keystore.go
type SimpleKeystore interface {
Sign(ctx context.Context, account string, data []byte) (signature []byte, err error)
Accounts(ctx context.Context) (accounts []string, err error)
}

var _ loop.Keystore = (SimpleKeystore)(nil)

// Txm manages transactions for the solana blockchain.
// simple implementation with no persistently stored txs
type Txm struct {
Expand Down

0 comments on commit f6d19a7

Please sign in to comment.