55 Keypair ,
66 PublicKey ,
77 sendAndConfirmRawTransaction ,
8- StakeProgram ,
8+ StakeProgram , SystemProgram ,
99 Transaction ,
1010 TransactionInstruction ,
1111} from '@solana/web3.js' ;
@@ -14,7 +14,7 @@ import { InvalidStakeAmount } from '../errors/sol';
1414import { ADDRESSES } from '../globals' ;
1515import {
1616 ApiCreatedStakes ,
17- InternalSolanaConfig ,
17+ InternalSolanaConfig , PublicNonceAccountInfo , PublicSignature ,
1818 SolanaStakeOptions ,
1919 SolanaTx ,
2020 SolNetworkStats ,
@@ -48,6 +48,27 @@ export class SolService extends Service {
4848 return connection ;
4949 }
5050
51+ /**
52+ * Get Kiln nonce account info
53+ * @private
54+ */
55+ private async getNonceAccount ( ) : Promise < PublicNonceAccountInfo > {
56+ const { data } = await api . get < PublicNonceAccountInfo > ( '/v1/sol/nonce-account' ) ;
57+ return data ;
58+ } ;
59+
60+ /**
61+ * Partially sign a hex encoded message with kiln nonce account
62+ * @param message
63+ * @private
64+ */
65+ private async partialSignWithNonceAccount ( message : string ) : Promise < PublicSignature [ ] > {
66+ const { data } = await api . post < PublicSignature [ ] > ( '/v1/sol/nonce-account/partial-sign' , {
67+ message,
68+ } ) ;
69+ return data ;
70+ } ;
71+
5172 /**
5273 * Craft Solana staking transaction
5374 * @param accountId id of the kiln account to use for the stake transaction
@@ -76,8 +97,20 @@ export class SolService extends Service {
7697 ) ;
7798 const memoProgram = 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr' ;
7899
100+ // Get nonce account info
101+ const nonceInfo = await this . getNonceAccount ( ) ;
102+ const nonceAccountPubKey = new PublicKey ( nonceInfo . nonce_account ) ;
103+ const connection = await this . getConnection ( ) ;
104+ const nonceAccount = await connection . getNonce ( nonceAccountPubKey ) ;
105+ if ( ! nonceAccount ) {
106+ throw new Error ( 'Could not fetch nonce account' ) ;
107+ }
108+
79109 const instructions = [
80- // memo the transaction with account id
110+ SystemProgram . nonceAdvance ( {
111+ noncePubkey : nonceAccountPubKey ,
112+ authorizedPubkey : nonceAccount . authorizedPubkey ,
113+ } ) ,
81114 new TransactionInstruction ( {
82115 keys : [
83116 {
@@ -120,12 +153,21 @@ export class SolService extends Service {
120153 ) ;
121154 }
122155
123- const connection = await this . getConnection ( ) ;
124- let blockhash = await connection . getLatestBlockhash ( 'finalized' ) ;
125- tx . recentBlockhash = blockhash . blockhash ;
156+ tx . recentBlockhash = nonceAccount . nonce ;
126157 tx . feePayer = staker ;
127158 tx . partialSign ( stakeKey ) ;
128159
160+ // Sign with nonce account
161+ const signatures = await this . partialSignWithNonceAccount ( tx . serializeMessage ( ) . toString ( 'hex' ) ) ;
162+ signatures . forEach ( ( signature : PublicSignature ) => {
163+ if ( signature . signature ) {
164+ tx . addSignature (
165+ new PublicKey ( signature . pubkey ) ,
166+ Buffer . from ( signature . signature , 'hex' ) ,
167+ ) ;
168+ }
169+ } ) ;
170+
129171 // Tag stake
130172 const stake : TaggedStake = {
131173 stakeAccount : stakeKey . publicKey . toString ( ) ,
@@ -155,7 +197,20 @@ export class SolService extends Service {
155197 const stakeAccountPubKey = new PublicKey ( stakeAccountAddress ) ;
156198 const walletPubKey = new PublicKey ( walletAddress ) ;
157199
200+ // Get nonce account info
201+ const nonceInfo = await this . getNonceAccount ( ) ;
202+ const nonceAccountPubKey = new PublicKey ( nonceInfo . nonce_account ) ;
203+ const connection = await this . getConnection ( ) ;
204+ const nonceAccount = await connection . getNonce ( nonceAccountPubKey ) ;
205+ if ( ! nonceAccount ) {
206+ throw new Error ( 'Could not fetch nonce account' ) ;
207+ }
208+
158209 const instructions = [
210+ SystemProgram . nonceAdvance ( {
211+ noncePubkey : nonceAccountPubKey ,
212+ authorizedPubkey : nonceAccount . authorizedPubkey ,
213+ } ) ,
159214 StakeProgram . deactivate ( {
160215 stakePubkey : stakeAccountPubKey ,
161216 authorizedPubkey : walletPubKey ,
@@ -164,10 +219,20 @@ export class SolService extends Service {
164219 tx . add ( ...instructions ) ;
165220
166221
167- const connection = await this . getConnection ( ) ;
168- let blockhash = await connection . getLatestBlockhash ( 'finalized' ) ;
169- tx . recentBlockhash = blockhash . blockhash ;
222+ tx . recentBlockhash = nonceAccount . nonce ;
170223 tx . feePayer = walletPubKey ;
224+
225+ // Sign with nonce account
226+ const signatures = await this . partialSignWithNonceAccount ( tx . serializeMessage ( ) . toString ( 'hex' ) ) ;
227+ signatures . forEach ( ( signature : PublicSignature ) => {
228+ if ( signature . signature ) {
229+ tx . addSignature (
230+ new PublicKey ( signature . pubkey ) ,
231+ Buffer . from ( signature . signature , 'hex' ) ,
232+ ) ;
233+ }
234+ } ) ;
235+
171236 return tx ;
172237 }
173238
@@ -184,8 +249,17 @@ export class SolService extends Service {
184249 ) : Promise < SolanaTx > {
185250 const stakeAccountPubKey = new PublicKey ( stakeAccountAddress ) ;
186251 const walletPubKey = new PublicKey ( walletAddress ) ;
187- let amount ;
252+
253+ // Get nonce account info
254+ const nonceInfo = await this . getNonceAccount ( ) ;
255+ const nonceAccountPubKey = new PublicKey ( nonceInfo . nonce_account ) ;
188256 const connection = await this . getConnection ( ) ;
257+ const nonceAccount = await connection . getNonce ( nonceAccountPubKey ) ;
258+ if ( ! nonceAccount ) {
259+ throw new Error ( 'Could not fetch nonce account' ) ;
260+ }
261+
262+ let amount ;
189263
190264 if ( ! amountToWithdraw ) {
191265 amount = await connection . getBalance ( stakeAccountPubKey ) ;
@@ -196,6 +270,10 @@ export class SolService extends Service {
196270 const tx = new Transaction ( ) ;
197271
198272 const instructions = [
273+ SystemProgram . nonceAdvance ( {
274+ noncePubkey : nonceAccountPubKey ,
275+ authorizedPubkey : nonceAccount . authorizedPubkey ,
276+ } ) ,
199277 StakeProgram . withdraw ( {
200278 stakePubkey : stakeAccountPubKey ,
201279 authorizedPubkey : walletPubKey ,
@@ -205,10 +283,20 @@ export class SolService extends Service {
205283 ] ;
206284 tx . add ( ...instructions ) ;
207285
208-
209- let blockhash = await connection . getLatestBlockhash ( 'finalized' ) ;
210- tx . recentBlockhash = blockhash . blockhash ;
286+ tx . recentBlockhash = nonceAccount . nonce ;
211287 tx . feePayer = walletPubKey ;
288+
289+ // Sign with nonce account
290+ const signatures = await this . partialSignWithNonceAccount ( tx . serializeMessage ( ) . toString ( 'hex' ) ) ;
291+ signatures . forEach ( ( signature : PublicSignature ) => {
292+ if ( signature . signature ) {
293+ tx . addSignature (
294+ new PublicKey ( signature . pubkey ) ,
295+ Buffer . from ( signature . signature , 'hex' ) ,
296+ ) ;
297+ }
298+ } ) ;
299+
212300 return tx ;
213301 }
214302
@@ -228,6 +316,15 @@ export class SolService extends Service {
228316 const sourcePubKey = new PublicKey ( stakeAccountSourceAddress ) ;
229317 const destinationPubKey = new PublicKey ( stakeAccountDestinationAddress ) ;
230318
319+ // Get nonce account info
320+ const nonceInfo = await this . getNonceAccount ( ) ;
321+ const nonceAccountPubKey = new PublicKey ( nonceInfo . nonce_account ) ;
322+ const connection = await this . getConnection ( ) ;
323+ const nonceAccount = await connection . getNonce ( nonceAccountPubKey ) ;
324+ if ( ! nonceAccount ) {
325+ throw new Error ( 'Could not fetch nonce account' ) ;
326+ }
327+
231328 const instructions = [
232329 StakeProgram . merge ( {
233330 stakePubkey : destinationPubKey ,
@@ -237,11 +334,20 @@ export class SolService extends Service {
237334 ] ;
238335 tx . add ( ...instructions ) ;
239336
240- const connection = await this . getConnection ( ) ;
241- let blockhash = await connection . getLatestBlockhash ( 'finalized' ) ;
242- tx . recentBlockhash = blockhash . blockhash ;
337+ tx . recentBlockhash = nonceAccount . nonce ;
243338 tx . feePayer = stakerPubKey ;
244339
340+ // Sign with nonce account
341+ const signatures = await this . partialSignWithNonceAccount ( tx . serializeMessage ( ) . toString ( 'hex' ) ) ;
342+ signatures . forEach ( ( signature : PublicSignature ) => {
343+ if ( signature . signature ) {
344+ tx . addSignature (
345+ new PublicKey ( signature . pubkey ) ,
346+ Buffer . from ( signature . signature , 'hex' ) ,
347+ ) ;
348+ }
349+ } ) ;
350+
245351 return tx ;
246352 }
247353
@@ -270,7 +376,6 @@ export class SolService extends Service {
270376
271377 const signatures = await this . fbSigner . signWithFB ( payload , this . testnet ? 'SOL_TEST' : 'SOL' , note ) ;
272378 signatures . signedMessages ?. forEach ( ( signedMessage : any ) => {
273- console . log ( signedMessage ) ;
274379 if ( signedMessage . derivationPath [ 3 ] == 0 && transaction . feePayer ) {
275380 transaction . addSignature ( transaction . feePayer , Buffer . from ( signedMessage . signature . fullSig , "hex" ) ) ;
276381 }
0 commit comments