@exodus/solana-lib 1.2.7 → 1.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/solana-lib",
3
- "version": "1.2.7",
3
+ "version": "1.2.8",
4
4
  "description": "Exodus internal Solana low-level library",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -22,5 +22,5 @@
22
22
  "create-hash": "~1.1.3",
23
23
  "tweetnacl": "^1.0.3"
24
24
  },
25
- "gitHead": "892c55db784616256e065a2c931a5e5611f5404f"
25
+ "gitHead": "0dc8adf4a7d4d6dc3d0785f5b5d39e0a6bfb23cd"
26
26
  }
@@ -130,15 +130,17 @@ class Tx {
130
130
  assert(amountLeft === 0, `Not enough balance to send ${amount} ${token.tokenSymbol}`)
131
131
  }
132
132
 
133
- static createStakeAccountTransaction({ address, amount, seed = SEED, recentBlockhash }) {
133
+ static createStakeAccountTransaction({ address, amount, seed = SEED, pool, recentBlockhash }) {
134
134
  const fromPubkey = new PublicKey(address)
135
135
  const stakeAddress = createStakeAddress(address, seed)
136
136
  const stakePublicKey = new PublicKey(stakeAddress)
137
+ const poolKey = new PublicKey(pool)
137
138
 
138
139
  const authorized = new Authorized(fromPubkey, fromPubkey) // staker, withdrawer
139
140
  const lockup = new Lockup(0, 0, fromPubkey) // no lockup
140
141
 
141
- const transaction = StakeProgram.createAccountWithSeed({
142
+ // create account instruction
143
+ const programTx = StakeProgram.createAccountWithSeed({
142
144
  fromPubkey,
143
145
  stakePubkey: stakePublicKey,
144
146
  basePubkey: fromPubkey,
@@ -147,6 +149,48 @@ class Tx {
147
149
  lockup,
148
150
  lamports: amount, // number
149
151
  })
152
+
153
+ // delegate funds instruction
154
+ const delegateTx = StakeProgram.delegate({
155
+ stakePubkey: stakePublicKey,
156
+ authorizedPubkey: fromPubkey,
157
+ votePubkey: poolKey, // pool vote key
158
+ })
159
+
160
+ const transaction = new Transaction({ recentBlockhash }).add(programTx).add(delegateTx)
161
+ return transaction
162
+ }
163
+
164
+ static undelegate({ address, stakeAddresses, recentBlockhash }) {
165
+ // undelegate all stake addresses
166
+ assert(Array.isArray(stakeAddresses), 'stakeAddresses Array is required')
167
+
168
+ const fromPubkey = new PublicKey(address)
169
+ const transaction = new Transaction({ recentBlockhash })
170
+
171
+ stakeAddresses.forEach((stakeAddress) => {
172
+ const stakePublicKey = new PublicKey(stakeAddress)
173
+ const programTx = StakeProgram.deactivate({
174
+ stakePubkey: stakePublicKey,
175
+ authorizedPubkey: fromPubkey,
176
+ })
177
+ transaction.add(programTx)
178
+ })
179
+
180
+ return transaction
181
+ }
182
+
183
+ static withdraw({ address, stakeAddresses, amount, recentBlockhash }) {
184
+ const fromPubkey = new PublicKey(address)
185
+ const stakeAddress = Array.isArray(stakeAddresses) ? stakeAddresses[0] : stakeAddresses
186
+ const stakePublicKey = new PublicKey(stakeAddress)
187
+
188
+ const transaction = StakeProgram.withdraw({
189
+ stakePubkey: stakePublicKey,
190
+ authorizedPubkey: fromPubkey,
191
+ toPubkey: fromPubkey,
192
+ lamports: amount,
193
+ })
150
194
  transaction.recentBlockhash = recentBlockhash
151
195
  return transaction
152
196
  }
@@ -182,6 +226,15 @@ class Tx {
182
226
  }
183
227
  return bs58.encode(this.transaction.signature)
184
228
  }
229
+
230
+ static getTxId(tx) {
231
+ let transaction = tx
232
+ if (tx instanceof Tx) transaction = tx.transaction
233
+ if (!transaction.signature) {
234
+ throw new Error('Cannot get txId, tx is not signed')
235
+ }
236
+ return bs58.encode(transaction.signature)
237
+ }
185
238
  }
186
239
 
187
240
  export default Tx
@@ -11,6 +11,11 @@ export function createUnsignedTx({
11
11
  destinationAddressType,
12
12
  isAssociatedTokenAccountActive, // true when recipient balance !== 0
13
13
  fromTokenAddresses, // sender token addresses
14
+ // Staking related:
15
+ method,
16
+ stakeAddresses,
17
+ seed,
18
+ pool,
14
19
  }: ParsedTransaction): UnsignedTransaction {
15
20
  return {
16
21
  txData: {
@@ -23,6 +28,11 @@ export function createUnsignedTx({
23
28
  destinationAddressType,
24
29
  isAssociatedTokenAccountActive,
25
30
  fromTokenAddresses,
31
+ // Staking related:
32
+ method,
33
+ stakeAddresses,
34
+ seed,
35
+ pool,
26
36
  },
27
37
  txMeta: {
28
38
  assetName: asset.name,
@@ -11,6 +11,10 @@ export function parseUnsignedTx(unsignedTx: UnsignedTransaction): ParsedTransact
11
11
  destinationAddressType,
12
12
  isAssociatedTokenAccountActive,
13
13
  fromTokenAddresses,
14
+ method,
15
+ stakeAddresses,
16
+ seed,
17
+ pool,
14
18
  ...txData
15
19
  } = unsignedTx.txData
16
20
 
@@ -26,5 +30,10 @@ export function parseUnsignedTx(unsignedTx: UnsignedTransaction): ParsedTransact
26
30
  destinationAddressType,
27
31
  isAssociatedTokenAccountActive,
28
32
  fromTokenAddresses,
33
+ // staking related
34
+ method,
35
+ stakeAddresses,
36
+ seed,
37
+ pool,
29
38
  }
30
39
  }
@@ -9,30 +9,70 @@ export function signUnsignedTx(
9
9
  const {
10
10
  from,
11
11
  to,
12
- amount,
12
+ amount: unitAmount,
13
13
  recentBlockhash,
14
+ // tokens related
14
15
  tokenName,
15
16
  destinationAddressType,
16
17
  isAssociatedTokenAccountActive,
17
18
  fromTokenAddresses,
19
+ // staking related
20
+ stakeAddresses,
21
+ method,
22
+ seed,
23
+ pool,
18
24
  } = unsignedTx.txData
19
25
 
20
26
  const asset = assets.solana
21
- const tx = new Transaction({
22
- from,
23
- to,
24
- amount: asset.currency.baseUnit(amount).toNumber(),
25
- recentBlockhash,
26
- tokenName,
27
- destinationAddressType,
28
- isAssociatedTokenAccountActive,
29
- fromTokenAddresses,
30
- })
27
+
28
+ const address = from
29
+ const amount = unitAmount ? asset.currency.baseUnit(unitAmount).toNumber() : unitAmount
30
+
31
+ let tx
32
+ switch (method) {
33
+ case 'delegate':
34
+ tx = Transaction.createStakeAccountTransaction({
35
+ address,
36
+ amount,
37
+ recentBlockhash,
38
+ seed,
39
+ pool,
40
+ })
41
+ break
42
+ case 'undelegate':
43
+ tx = Transaction.undelegate({
44
+ address,
45
+ stakeAddresses,
46
+ recentBlockhash,
47
+ })
48
+ break
49
+ case 'withdraw':
50
+ tx = Transaction.withdraw({
51
+ address,
52
+ stakeAddresses,
53
+ amount,
54
+ recentBlockhash,
55
+ })
56
+ break
57
+ default:
58
+ // SOL and Token tx
59
+ tx = new Transaction({
60
+ from,
61
+ to,
62
+ amount,
63
+ recentBlockhash,
64
+ tokenName,
65
+ destinationAddressType,
66
+ isAssociatedTokenAccountActive,
67
+ fromTokenAddresses,
68
+ })
69
+ break
70
+ }
31
71
 
32
72
  // sign plain tx
33
73
  Transaction.sign(tx, privateKey)
34
- const rawTx = tx.serialize()
35
- const txId = tx.getTxId()
74
+ const rawTx = Transaction.serialize(tx)
75
+ const txId = Transaction.getTxId(tx)
36
76
 
37
77
  return { txId, rawTx }
38
78
  }
@@ -298,68 +298,6 @@ export class StakeInstruction {
298
298
  }
299
299
  }
300
300
 
301
- /**
302
- * Decode an authorize stake instruction and retrieve the instruction params.
303
- */
304
- static decodeAuthorize(instruction: TransactionInstruction): AuthorizeStakeParams {
305
- this.checkProgramId(instruction.programId)
306
- this.checkKeyLength(instruction.keys, 3)
307
- const { newAuthorized, stakeAuthorizationType } = decodeData(
308
- STAKE_INSTRUCTION_LAYOUTS.Authorize,
309
- instruction.data
310
- )
311
-
312
- return {
313
- stakePubkey: instruction.keys[0].pubkey,
314
- authorizedPubkey: instruction.keys[2].pubkey,
315
- newAuthorizedPubkey: new PublicKey(newAuthorized),
316
- stakeAuthorizationType: {
317
- index: stakeAuthorizationType,
318
- },
319
- }
320
- }
321
-
322
- /**
323
- * Decode an authorize-with-seed stake instruction and retrieve the instruction params.
324
- */
325
- static decodeAuthorizeWithSeed(
326
- instruction: TransactionInstruction
327
- ): AuthorizeWithSeedStakeParams {
328
- this.checkProgramId(instruction.programId)
329
- this.checkKeyLength(instruction.keys, 2)
330
- const { newAuthorized, stakeAuthorizationType, authoritySeed, authorityOwner } = decodeData(
331
- STAKE_INSTRUCTION_LAYOUTS.AuthorizeWithSeed,
332
- instruction.data
333
- )
334
-
335
- return {
336
- stakePubkey: instruction.keys[0].pubkey,
337
- authorityBase: instruction.keys[1].pubkey,
338
- authoritySeed: authoritySeed,
339
- authorityOwner: new PublicKey(authorityOwner),
340
- newAuthorizedPubkey: new PublicKey(newAuthorized),
341
- stakeAuthorizationType: {
342
- index: stakeAuthorizationType,
343
- },
344
- }
345
- }
346
-
347
- /**
348
- * Decode a split stake instruction and retrieve the instruction params.
349
- */
350
- static decodeSplit(instruction: TransactionInstruction): SplitStakeParams {
351
- this.checkProgramId(instruction.programId)
352
- this.checkKeyLength(instruction.keys, 3)
353
- const { lamports } = decodeData(STAKE_INSTRUCTION_LAYOUTS.Split, instruction.data)
354
-
355
- return {
356
- stakePubkey: instruction.keys[0].pubkey,
357
- splitStakePubkey: instruction.keys[1].pubkey,
358
- authorizedPubkey: instruction.keys[2].pubkey,
359
- lamports,
360
- }
361
- }
362
-
363
301
  /**
364
302
  * Decode a withdraw stake instruction and retrieve the instruction params.
365
303
  */
@@ -543,92 +481,6 @@ export class StakeProgram {
543
481
  })
544
482
  }
545
483
 
546
- /**
547
- * Generate a Transaction that authorizes a new PublicKey as Staker
548
- * or Withdrawer on the Stake account.
549
- */
550
- static authorize(params: AuthorizeStakeParams): Transaction {
551
- const { stakePubkey, authorizedPubkey, newAuthorizedPubkey, stakeAuthorizationType } = params
552
-
553
- const type = STAKE_INSTRUCTION_LAYOUTS.Authorize
554
- const data = encodeData(type, {
555
- newAuthorized: newAuthorizedPubkey.toBuffer(),
556
- stakeAuthorizationType: stakeAuthorizationType.index,
557
- })
558
-
559
- return new Transaction().add({
560
- keys: [
561
- { pubkey: stakePubkey, isSigner: false, isWritable: true },
562
- { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: true },
563
- { pubkey: authorizedPubkey, isSigner: true, isWritable: false },
564
- ],
565
- programId: this.programId,
566
- data,
567
- })
568
- }
569
-
570
- /**
571
- * Generate a Transaction that authorizes a new PublicKey as Staker
572
- * or Withdrawer on the Stake account.
573
- */
574
- static authorizeWithSeed(params: AuthorizeWithSeedStakeParams): Transaction {
575
- const {
576
- stakePubkey,
577
- authorityBase,
578
- authoritySeed,
579
- authorityOwner,
580
- newAuthorizedPubkey,
581
- stakeAuthorizationType,
582
- } = params
583
-
584
- const type = STAKE_INSTRUCTION_LAYOUTS.AuthorizeWithSeed
585
- const data = encodeData(type, {
586
- newAuthorized: newAuthorizedPubkey.toBuffer(),
587
- stakeAuthorizationType: stakeAuthorizationType.index,
588
- authoritySeed: authoritySeed,
589
- authorityOwner: authorityOwner.toBuffer(),
590
- })
591
-
592
- return new Transaction().add({
593
- keys: [
594
- { pubkey: stakePubkey, isSigner: false, isWritable: true },
595
- { pubkey: authorityBase, isSigner: true, isWritable: false },
596
- ],
597
- programId: this.programId,
598
- data,
599
- })
600
- }
601
-
602
- /**
603
- * Generate a Transaction that splits Stake tokens into another stake account
604
- */
605
- static split(params: SplitStakeParams): Transaction {
606
- const { stakePubkey, authorizedPubkey, splitStakePubkey, lamports } = params
607
-
608
- const transaction = new Transaction()
609
- transaction.add(
610
- SystemProgram.createAccount({
611
- fromPubkey: authorizedPubkey,
612
- newAccountPubkey: splitStakePubkey,
613
- lamports: 0,
614
- space: this.space,
615
- programId: this.programId,
616
- })
617
- )
618
- const type = STAKE_INSTRUCTION_LAYOUTS.Split
619
- const data = encodeData(type, { lamports })
620
-
621
- return transaction.add({
622
- keys: [
623
- { pubkey: stakePubkey, isSigner: false, isWritable: true },
624
- { pubkey: splitStakePubkey, isSigner: false, isWritable: true },
625
- { pubkey: authorizedPubkey, isSigner: true, isWritable: false },
626
- ],
627
- programId: this.programId,
628
- data,
629
- })
630
- }
631
-
632
484
  /**
633
485
  * Generate a Transaction that withdraws deactivated Stake tokens.
634
486
  */