@@ -6,7 +6,9 @@ package relayinterface
6
6
import (
7
7
"context"
8
8
"encoding/binary"
9
+ "fmt"
9
10
"io"
11
+ "log"
10
12
"os"
11
13
"path/filepath"
12
14
"sync"
@@ -18,20 +20,27 @@ import (
18
20
"github.com/gagliardetto/solana-go/rpc/ws"
19
21
"github.com/gagliardetto/solana-go/text"
20
22
"github.com/stretchr/testify/require"
23
+ "github.com/test-go/testify/mock"
21
24
22
25
"github.com/smartcontractkit/chainlink-common/pkg/codec"
23
26
"github.com/smartcontractkit/chainlink-common/pkg/logger"
24
27
commontestutils "github.com/smartcontractkit/chainlink-common/pkg/loop/testutils"
28
+ "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest"
25
29
"github.com/smartcontractkit/chainlink-common/pkg/types"
26
30
. "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with .
27
31
"github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives"
32
+ commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils"
28
33
"github.com/smartcontractkit/chainlink-common/pkg/utils/tests"
29
34
30
35
contract "github.com/smartcontractkit/chainlink-solana/contracts/generated/contract_reader_interface"
31
36
"github.com/smartcontractkit/chainlink-solana/integration-tests/solclient"
32
37
"github.com/smartcontractkit/chainlink-solana/integration-tests/utils"
33
38
"github.com/smartcontractkit/chainlink-solana/pkg/solana/chainreader"
39
+ "github.com/smartcontractkit/chainlink-solana/pkg/solana/chainwriter"
40
+ "github.com/smartcontractkit/chainlink-solana/pkg/solana/client"
34
41
"github.com/smartcontractkit/chainlink-solana/pkg/solana/config"
42
+ "github.com/smartcontractkit/chainlink-solana/pkg/solana/txm"
43
+ keyMocks "github.com/smartcontractkit/chainlink-solana/pkg/solana/txm/mocks"
35
44
solanautils "github.com/smartcontractkit/chainlink-solana/pkg/solana/utils"
36
45
)
37
46
@@ -124,14 +133,17 @@ type SolanaChainComponentsInterfaceTesterHelper[T TestingT[T]] interface {
124
133
Context (t T ) context.Context
125
134
Logger (t T ) logger.Logger
126
135
GetJSONEncodedIDL (t T ) []byte
127
- CreateAccount (t T , value uint64 ) solana.PublicKey
136
+ CreateAccount (t T , it SolanaChainComponentsInterfaceTester [T ], value uint64 ) solana.PublicKey
137
+ TXM () * txm.TxManager
138
+ SolanaClient () * client.Client
128
139
}
129
140
130
141
type SolanaChainComponentsInterfaceTester [T TestingT [T ]] struct {
131
142
TestSelectionSupport
132
143
Helper SolanaChainComponentsInterfaceTesterHelper [T ]
133
144
cr * chainreader.SolanaChainReaderService
134
145
chainReaderConfig config.ChainReader
146
+ chainWriterConfig chainwriter.ChainWriterConfig
135
147
}
136
148
137
149
func (it * SolanaChainComponentsInterfaceTester [T ]) Setup (t T ) {
@@ -179,6 +191,41 @@ func (it *SolanaChainComponentsInterfaceTester[T]) Setup(t T) {
179
191
},
180
192
},
181
193
}
194
+
195
+ it .chainWriterConfig = chainwriter.ChainWriterConfig {
196
+ Programs : map [string ]chainwriter.ProgramConfig {
197
+ AnyContractName : {
198
+ IDL : string (it .Helper .GetJSONEncodedIDL (t )),
199
+ Methods : map [string ]chainwriter.MethodConfig {
200
+ "initialize" : {
201
+ FromAddress : solana .MustPrivateKeyFromBase58 (solclient .DefaultPrivateKeysSolValidator [1 ]).PublicKey ().String (),
202
+ InputModifications : nil ,
203
+ ChainSpecificName : "initialize" ,
204
+ LookupTables : chainwriter.LookupTables {},
205
+ Accounts : []chainwriter.Lookup {
206
+ chainwriter.PDALookups {
207
+ Name : "Account" ,
208
+ PublicKey : chainwriter.AccountConstant {
209
+ Name : "ProgramID" ,
210
+ Address : programPubKey ,
211
+ },
212
+ Seeds : []chainwriter.Seed {
213
+ {Static : []byte ("data" )},
214
+ {Dynamic : chainwriter.AccountLookup {
215
+ Name : "TestIDX" ,
216
+ Location : "testIdx" ,
217
+ }},
218
+ },
219
+ IsWritable : true ,
220
+ IsSigner : false ,
221
+ },
222
+ },
223
+ DebugIDLocation : "" ,
224
+ },
225
+ },
226
+ },
227
+ },
228
+ }
182
229
}
183
230
184
231
func (it * SolanaChainComponentsInterfaceTester [T ]) Name () string {
@@ -210,14 +257,18 @@ func (it *SolanaChainComponentsInterfaceTester[T]) GetContractReader(t T) types.
210
257
}
211
258
212
259
func (it * SolanaChainComponentsInterfaceTester [T ]) GetContractWriter (t T ) types.ContractWriter {
213
- return nil
260
+ cw , err := chainwriter .NewSolanaChainWriterService (it .Helper .Logger (t ), it .Helper .SolanaClient (), * it .Helper .TXM (), nil , it .chainWriterConfig )
261
+ require .NoError (t , err )
262
+
263
+ servicetest .Run (t , cw )
264
+ return cw
214
265
}
215
266
216
267
func (it * SolanaChainComponentsInterfaceTester [T ]) GetBindings (t T ) []types.BoundContract {
217
268
// Create a new account with fresh state for each test
218
269
return []types.BoundContract {
219
- {Name : AnyContractName , Address : it .Helper .CreateAccount (t , AnyValueToReadWithoutAnArgument ).String ()},
220
- {Name : AnySecondContractName , Address : it .Helper .CreateAccount (t , AnyDifferentValueToReadWithoutAnArgument ).String ()},
270
+ {Name : AnyContractName , Address : it .Helper .CreateAccount (t , * it , AnyValueToReadWithoutAnArgument ).String ()},
271
+ {Name : AnySecondContractName , Address : it .Helper .CreateAccount (t , * it , AnyDifferentValueToReadWithoutAnArgument ).String ()},
221
272
}
222
273
}
223
274
@@ -240,6 +291,8 @@ type helper struct {
240
291
idlBts []byte
241
292
nonce uint64
242
293
nonceMu sync.Mutex
294
+ txm txm.TxManager
295
+ sc * client.Client
243
296
}
244
297
245
298
func (h * helper ) Init (t * testing.T ) {
@@ -256,17 +309,55 @@ func (h *helper) Init(t *testing.T) {
256
309
257
310
solanautils .FundAccounts (t , []solana.PrivateKey {privateKey }, h .rpcClient )
258
311
312
+ cfg := config .NewDefault ()
313
+ solanaClient , err := client .NewClient (h .rpcURL , cfg , 5 * time .Second , nil )
314
+ require .NoError (t , err )
315
+
316
+ h .sc = solanaClient
317
+
318
+ loader := commonutils .NewLazyLoad (func () (client.ReaderWriter , error ) { return solanaClient , nil })
319
+ mkey := keyMocks .NewSimpleKeystore (t )
320
+ mkey .On ("Sign" , mock .Anything , privateKey .PublicKey ().String (), mock .Anything ).Return (func (_ context.Context , _ string , data []byte ) []byte {
321
+ sig , _ := privateKey .Sign (data )
322
+ verifySignature (privateKey .PublicKey (), sig [:], data )
323
+ fmt .Printf ("Signed for %s: %x\n " , privateKey .PublicKey ().String (), sig )
324
+ return sig [:]
325
+ }, nil )
326
+ lggr := logger .Test (t )
327
+
328
+ txm := txm .NewTxm ("localnet" , loader , nil , cfg , mkey , lggr )
329
+ txm .Start (tests .Context (t ))
330
+ h .txm = txm
331
+
259
332
pubkey , err := solana .PublicKeyFromBase58 (programPubKey )
260
333
require .NoError (t , err )
261
334
262
335
contract .SetProgramID (pubkey )
263
336
h .programID = pubkey
264
337
}
265
338
339
+ func verifySignature (publicKey solana.PublicKey , signature []byte , message []byte ) bool {
340
+ valid := publicKey .Verify (message , solana .SignatureFromBytes (signature ))
341
+ if valid {
342
+ log .Printf ("Signature is valid for public key: %s\n " , publicKey .String ())
343
+ } else {
344
+ log .Printf ("Signature is invalid for public key: %s\n " , publicKey .String ())
345
+ }
346
+ return valid
347
+ }
348
+
266
349
func (h * helper ) RPCClient () * chainreader.RPCClientWrapper {
267
350
return & chainreader.RPCClientWrapper {Client : h .rpcClient }
268
351
}
269
352
353
+ func (h * helper ) TXM () * txm.TxManager {
354
+ return & h .txm
355
+ }
356
+
357
+ func (h * helper ) SolanaClient () * client.Client {
358
+ return h .sc
359
+ }
360
+
270
361
func (h * helper ) Context (t * testing.T ) context.Context {
271
362
return tests .Context (t )
272
363
}
@@ -298,7 +389,7 @@ func (h *helper) GetJSONEncodedIDL(t *testing.T) []byte {
298
389
return h .idlBts
299
390
}
300
391
301
- func (h * helper ) CreateAccount (t * testing.T , value uint64 ) solana.PublicKey {
392
+ func (h * helper ) CreateAccount (t * testing.T , it SolanaChainComponentsInterfaceTester [ * testing. T ], value uint64 ) solana.PublicKey {
302
393
t .Helper ()
303
394
304
395
// avoid collisions in parallel tests
@@ -317,7 +408,7 @@ func (h *helper) CreateAccount(t *testing.T, value uint64) solana.PublicKey {
317
408
privateKey , err := solana .PrivateKeyFromBase58 (solclient .DefaultPrivateKeysSolValidator [1 ])
318
409
require .NoError (t , err )
319
410
320
- h .runInitialize (t , nonce , value , pubKey , func (key solana.PublicKey ) * solana.PrivateKey {
411
+ h .runInitialize (t , it , nonce , value , pubKey , func (key solana.PublicKey ) * solana.PrivateKey {
321
412
return & privateKey
322
413
}, privateKey .PublicKey ())
323
414
@@ -326,6 +417,7 @@ func (h *helper) CreateAccount(t *testing.T, value uint64) solana.PublicKey {
326
417
327
418
func (h * helper ) runInitialize (
328
419
t * testing.T ,
420
+ it SolanaChainComponentsInterfaceTester [* testing.T ],
329
421
nonce uint64 ,
330
422
value uint64 ,
331
423
data solana.PublicKey ,
@@ -334,10 +426,33 @@ func (h *helper) runInitialize(
334
426
) {
335
427
t .Helper ()
336
428
337
- inst , err := contract .NewInitializeInstruction (nonce * value , value , data , payer , solana .SystemProgramID ).ValidateAndBuild ()
429
+ cw := it .GetContractWriter (t )
430
+
431
+ args := map [string ]interface {}{
432
+ "testIdx" : nonce * value ,
433
+ "value" : value ,
434
+ }
435
+
436
+ buf := make ([]byte , 8 )
437
+ binary .LittleEndian .PutUint64 (buf , nonce * value )
438
+
439
+ data , _ , err := solana .FindProgramAddress (
440
+ [][]byte {
441
+ []byte ("data" ), // Seed 1
442
+ buf , // Seed 2 (test_idx)
443
+ },
444
+ solana .MustPublicKeyFromBase58 (programPubKey ), // The program ID
445
+ )
338
446
require .NoError (t , err )
339
447
340
- h .sendInstruction (t , inst , signerFunc , payer )
448
+ fmt .Printf ("Derived PDA in test: %s\n " , data .String ())
449
+
450
+ SubmitTransactionToCW (t , & it , cw , "initialize" , args , types.BoundContract {Name : AnyContractName , Address : h .programID .String ()}, types .Finalized )
451
+
452
+ // inst, err := contract.NewInitializeInstruction(nonce*value, value, data, payer, solana.SystemProgramID).ValidateAndBuild()
453
+ // require.NoError(t, err)
454
+
455
+ // h.sendInstruction(t, inst, signerFunc, payer)
341
456
}
342
457
343
458
func (h * helper ) sendInstruction (
0 commit comments