@exodus/solana-lib 1.7.5 → 1.8.0
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 +12 -4
- package/src/constants.js +1 -1
- package/src/encode.js +3 -20
- package/src/helpers/metadata-schema.js +4 -6
- package/src/helpers/metaplex-transfer.js +1 -1
- package/src/helpers/spl-token.js +411 -8
- package/src/helpers/tokenTransfer.js +4 -8
- package/src/index.js +1 -1
- package/src/key-identifier.js +42 -45
- package/src/keypair.js +1 -1
- package/src/magiceden/coders.js +2 -6
- package/src/magiceden/escrow-program.js +11 -11
- package/src/transaction.js +22 -9
- package/src/tx/build-raw-transaction.js +3 -3
- package/src/tx/common.js +1 -0
- package/src/tx/decode-tx-instructions.js +29 -15
- package/src/tx/prepare-for-signing.js +15 -8
- package/src/tx/sign-hardware.js +1 -3
- package/src/tx/sign-message.js +4 -5
- package/src/tx/simulate-and-sign-tx.js +18 -17
- package/src/vendor/compute-budget-program.js +180 -0
- package/src/vendor/constants.js +8 -0
- package/src/vendor/index.js +2 -0
- package/src/vendor/message.js +10 -9
- package/src/vendor/publickey.js +24 -37
- package/src/vendor/stake-program.js +32 -32
- package/src/vendor/system-program.js +52 -52
- package/src/vendor/transaction.js +35 -23
- package/src/vendor/utils/shortvec-encoding.js +2 -1
- package/src/vendor/utils/to-buffer.js +5 -3
- package/src/vendor/utils/blockhash.js +0 -3
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import * as BufferLayout from '@exodus/buffer-layout'
|
|
2
|
+
|
|
3
|
+
import { encodeData, decodeData } from './instruction'
|
|
4
|
+
import { PublicKey } from './publickey'
|
|
5
|
+
import { TransactionInstruction } from './transaction'
|
|
6
|
+
|
|
7
|
+
// 1 microLamport = 0.000001 lamports
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Compute Budget Instruction class
|
|
11
|
+
*/
|
|
12
|
+
// eslint-disable-next-line unicorn/no-static-only-class
|
|
13
|
+
export class ComputeBudgetInstruction {
|
|
14
|
+
/**
|
|
15
|
+
* Decode a compute budget instruction and retrieve the instruction type.
|
|
16
|
+
*/
|
|
17
|
+
static decodeInstructionType(instruction) {
|
|
18
|
+
this.checkProgramId(instruction.programId)
|
|
19
|
+
|
|
20
|
+
const instructionTypeLayout = BufferLayout.u8('instruction')
|
|
21
|
+
const typeIndex = instructionTypeLayout.decode(instruction.data)
|
|
22
|
+
|
|
23
|
+
let type
|
|
24
|
+
for (const [ixType, layout] of Object.entries(COMPUTE_BUDGET_INSTRUCTION_LAYOUTS)) {
|
|
25
|
+
if (layout.index === typeIndex) {
|
|
26
|
+
type = ixType
|
|
27
|
+
break
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!type) {
|
|
32
|
+
throw new Error('Instruction type incorrect; not a ComputeBudgetInstruction')
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return type
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Decode request units compute budget instruction and retrieve the instruction params.
|
|
40
|
+
*/
|
|
41
|
+
static decodeRequestUnits(instruction) {
|
|
42
|
+
this.checkProgramId(instruction.programId)
|
|
43
|
+
const { units, additionalFee } = decodeData(
|
|
44
|
+
COMPUTE_BUDGET_INSTRUCTION_LAYOUTS.RequestUnits,
|
|
45
|
+
instruction.data
|
|
46
|
+
)
|
|
47
|
+
return { units, additionalFee }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Decode request heap frame compute budget instruction and retrieve the instruction params.
|
|
52
|
+
*/
|
|
53
|
+
static decodeRequestHeapFrame(instruction) {
|
|
54
|
+
this.checkProgramId(instruction.programId)
|
|
55
|
+
const { bytes } = decodeData(
|
|
56
|
+
COMPUTE_BUDGET_INSTRUCTION_LAYOUTS.RequestHeapFrame,
|
|
57
|
+
instruction.data
|
|
58
|
+
)
|
|
59
|
+
return { bytes }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Decode set compute unit limit compute budget instruction and retrieve the instruction params.
|
|
64
|
+
*/
|
|
65
|
+
static decodeSetComputeUnitLimit(instruction) {
|
|
66
|
+
this.checkProgramId(instruction.programId)
|
|
67
|
+
const { units } = decodeData(
|
|
68
|
+
COMPUTE_BUDGET_INSTRUCTION_LAYOUTS.SetComputeUnitLimit,
|
|
69
|
+
instruction.data
|
|
70
|
+
)
|
|
71
|
+
return { units }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Decode set compute unit price compute budget instruction and retrieve the instruction params.
|
|
76
|
+
*/
|
|
77
|
+
static decodeSetComputeUnitPrice(instruction) {
|
|
78
|
+
this.checkProgramId(instruction.programId)
|
|
79
|
+
const { microLamports } = decodeData(
|
|
80
|
+
COMPUTE_BUDGET_INSTRUCTION_LAYOUTS.SetComputeUnitPrice,
|
|
81
|
+
instruction.data
|
|
82
|
+
)
|
|
83
|
+
return { microLamports }
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @internal
|
|
88
|
+
*/
|
|
89
|
+
static checkProgramId(programId) {
|
|
90
|
+
if (!programId.equals(ComputeBudgetProgram.programId)) {
|
|
91
|
+
throw new Error('invalid instruction; programId is not ComputeBudgetProgram')
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* An enumeration of valid ComputeBudget InstructionType's
|
|
98
|
+
* @internal
|
|
99
|
+
*/
|
|
100
|
+
export const COMPUTE_BUDGET_INSTRUCTION_LAYOUTS = Object.freeze({
|
|
101
|
+
RequestUnits: {
|
|
102
|
+
index: 0,
|
|
103
|
+
layout: BufferLayout.struct([
|
|
104
|
+
BufferLayout.u8('instruction'),
|
|
105
|
+
BufferLayout.u32('units'),
|
|
106
|
+
BufferLayout.u32('additionalFee'),
|
|
107
|
+
]),
|
|
108
|
+
},
|
|
109
|
+
RequestHeapFrame: {
|
|
110
|
+
index: 1,
|
|
111
|
+
layout: BufferLayout.struct([BufferLayout.u8('instruction'), BufferLayout.u32('bytes')]),
|
|
112
|
+
},
|
|
113
|
+
SetComputeUnitLimit: {
|
|
114
|
+
index: 2,
|
|
115
|
+
layout: BufferLayout.struct([BufferLayout.u8('instruction'), BufferLayout.u32('units')]),
|
|
116
|
+
},
|
|
117
|
+
SetComputeUnitPrice: {
|
|
118
|
+
index: 3,
|
|
119
|
+
layout: BufferLayout.struct([
|
|
120
|
+
BufferLayout.u8('instruction'),
|
|
121
|
+
BufferLayout.ns64('microLamports'),
|
|
122
|
+
]),
|
|
123
|
+
},
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Factory class for transaction instructions to interact with the Compute Budget program
|
|
128
|
+
*/
|
|
129
|
+
// eslint-disable-next-line unicorn/no-static-only-class
|
|
130
|
+
export class ComputeBudgetProgram {
|
|
131
|
+
/**
|
|
132
|
+
* Public key that identifies the Compute Budget program
|
|
133
|
+
*/
|
|
134
|
+
static programId = new PublicKey('ComputeBudget111111111111111111111111111111')
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* @deprecated Instead, call {@link setComputeUnitLimit} and/or {@link setComputeUnitPrice}
|
|
138
|
+
*/
|
|
139
|
+
static requestUnits(params) {
|
|
140
|
+
const type = COMPUTE_BUDGET_INSTRUCTION_LAYOUTS.RequestUnits
|
|
141
|
+
const data = encodeData(type, params)
|
|
142
|
+
return new TransactionInstruction({
|
|
143
|
+
keys: [],
|
|
144
|
+
programId: this.programId,
|
|
145
|
+
data,
|
|
146
|
+
})
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
static requestHeapFrame(params) {
|
|
150
|
+
const type = COMPUTE_BUDGET_INSTRUCTION_LAYOUTS.RequestHeapFrame
|
|
151
|
+
const data = encodeData(type, params)
|
|
152
|
+
return new TransactionInstruction({
|
|
153
|
+
keys: [],
|
|
154
|
+
programId: this.programId,
|
|
155
|
+
data,
|
|
156
|
+
})
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
static setComputeUnitLimit(params) {
|
|
160
|
+
const type = COMPUTE_BUDGET_INSTRUCTION_LAYOUTS.SetComputeUnitLimit
|
|
161
|
+
const data = encodeData(type, params)
|
|
162
|
+
return new TransactionInstruction({
|
|
163
|
+
keys: [],
|
|
164
|
+
programId: this.programId,
|
|
165
|
+
data,
|
|
166
|
+
})
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
static setComputeUnitPrice(params) {
|
|
170
|
+
const type = COMPUTE_BUDGET_INSTRUCTION_LAYOUTS.SetComputeUnitPrice
|
|
171
|
+
const data = encodeData(type, {
|
|
172
|
+
microLamports: Number(params.microLamports), // replaced from BigInt
|
|
173
|
+
})
|
|
174
|
+
return new TransactionInstruction({
|
|
175
|
+
keys: [],
|
|
176
|
+
programId: this.programId,
|
|
177
|
+
data,
|
|
178
|
+
})
|
|
179
|
+
}
|
|
180
|
+
}
|
package/src/vendor/index.js
CHANGED
|
@@ -4,6 +4,8 @@ export * from './message'
|
|
|
4
4
|
export * from './nonce-account'
|
|
5
5
|
export * from './publickey'
|
|
6
6
|
export * from './system-program'
|
|
7
|
+
export * from './compute-budget-program'
|
|
7
8
|
export * from './stake-program'
|
|
8
9
|
export * from './sysvar'
|
|
9
10
|
export * from './transaction'
|
|
11
|
+
export * from './constants'
|
package/src/vendor/message.js
CHANGED
|
@@ -4,7 +4,7 @@ import * as BufferLayout from '@exodus/buffer-layout'
|
|
|
4
4
|
import { PublicKey } from './publickey'
|
|
5
5
|
|
|
6
6
|
import * as Layout from './utils/layout'
|
|
7
|
-
import { PACKET_DATA_SIZE } from './
|
|
7
|
+
import { PACKET_DATA_SIZE } from './constants'
|
|
8
8
|
import * as shortvec from './utils/shortvec-encoding'
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -73,23 +73,24 @@ export class Message {
|
|
|
73
73
|
if (index < 0) {
|
|
74
74
|
throw new Error(`unknown signer: ${signer.toString()}`)
|
|
75
75
|
}
|
|
76
|
+
|
|
76
77
|
return index
|
|
77
78
|
}
|
|
78
79
|
|
|
79
80
|
serialize() {
|
|
80
81
|
const numKeys = this.accountKeys.length
|
|
81
82
|
|
|
82
|
-
|
|
83
|
+
const keyCount = []
|
|
83
84
|
shortvec.encodeLength(keyCount, numKeys)
|
|
84
85
|
|
|
85
86
|
const instructions = this.instructions.map((instruction) => {
|
|
86
87
|
const { accounts, programIdIndex } = instruction
|
|
87
88
|
const data = bs58.decode(instruction.data)
|
|
88
89
|
|
|
89
|
-
|
|
90
|
+
const keyIndicesCount = []
|
|
90
91
|
shortvec.encodeLength(keyIndicesCount, accounts.length)
|
|
91
92
|
|
|
92
|
-
|
|
93
|
+
const dataCount = []
|
|
93
94
|
shortvec.encodeLength(dataCount, data.length)
|
|
94
95
|
|
|
95
96
|
return {
|
|
@@ -101,7 +102,7 @@ export class Message {
|
|
|
101
102
|
}
|
|
102
103
|
})
|
|
103
104
|
|
|
104
|
-
|
|
105
|
+
const instructionCount = []
|
|
105
106
|
shortvec.encodeLength(instructionCount, instructions.length)
|
|
106
107
|
let instructionBuffer = Buffer.alloc(PACKET_DATA_SIZE)
|
|
107
108
|
Buffer.from(instructionCount).copy(instructionBuffer)
|
|
@@ -143,7 +144,7 @@ export class Message {
|
|
|
143
144
|
recentBlockhash: bs58.decode(this.recentBlockhash),
|
|
144
145
|
}
|
|
145
146
|
|
|
146
|
-
|
|
147
|
+
const signData = Buffer.alloc(2048)
|
|
147
148
|
const length = signDataLayout.encode(transaction, signData)
|
|
148
149
|
instructionBuffer.copy(signData, length)
|
|
149
150
|
return signData.slice(0, length + instructionBuffer.length)
|
|
@@ -161,7 +162,7 @@ export class Message {
|
|
|
161
162
|
const numReadonlyUnsignedAccounts = byteArray.shift()
|
|
162
163
|
|
|
163
164
|
const accountCount = shortvec.decodeLength(byteArray)
|
|
164
|
-
|
|
165
|
+
const accountKeys = []
|
|
165
166
|
for (let i = 0; i < accountCount; i++) {
|
|
166
167
|
const account = byteArray.slice(0, PUBKEY_LENGTH)
|
|
167
168
|
byteArray = byteArray.slice(PUBKEY_LENGTH)
|
|
@@ -172,9 +173,9 @@ export class Message {
|
|
|
172
173
|
byteArray = byteArray.slice(PUBKEY_LENGTH)
|
|
173
174
|
|
|
174
175
|
const instructionCount = shortvec.decodeLength(byteArray)
|
|
175
|
-
|
|
176
|
+
const instructions = []
|
|
176
177
|
for (let i = 0; i < instructionCount; i++) {
|
|
177
|
-
|
|
178
|
+
const instruction = Object.create(null)
|
|
178
179
|
instruction.programIdIndex = byteArray.shift()
|
|
179
180
|
const accountCount = shortvec.decodeLength(byteArray)
|
|
180
181
|
instruction.accounts = byteArray.slice(0, accountCount)
|
package/src/vendor/publickey.js
CHANGED
|
@@ -4,7 +4,7 @@ import nacl from 'tweetnacl'
|
|
|
4
4
|
import createHash from 'create-hash'
|
|
5
5
|
|
|
6
6
|
// $FlowFixMe
|
|
7
|
-
|
|
7
|
+
const naclLowLevel = nacl.lowlevel
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Maximum length of derived pubkey seed
|
|
@@ -27,6 +27,7 @@ export class PublicKey {
|
|
|
27
27
|
if (decoded.length !== 32) {
|
|
28
28
|
throw new Error(`Invalid public key input`)
|
|
29
29
|
}
|
|
30
|
+
|
|
30
31
|
this._bn = new BN(decoded)
|
|
31
32
|
} else {
|
|
32
33
|
this._bn = new BN(value)
|
|
@@ -100,14 +101,16 @@ export class PublicKey {
|
|
|
100
101
|
let address
|
|
101
102
|
while (nonce !== 0) {
|
|
102
103
|
try {
|
|
103
|
-
const seedsWithNonce = seeds
|
|
104
|
+
const seedsWithNonce = [...seeds, Buffer.from([nonce])]
|
|
104
105
|
address = this.createProgramAddress(seedsWithNonce, programId)
|
|
105
|
-
} catch
|
|
106
|
+
} catch {
|
|
106
107
|
nonce--
|
|
107
108
|
continue
|
|
108
109
|
}
|
|
110
|
+
|
|
109
111
|
return [address, nonce]
|
|
110
112
|
}
|
|
113
|
+
|
|
111
114
|
throw new Error('Unable to find a viable program address nonce')
|
|
112
115
|
}
|
|
113
116
|
|
|
@@ -121,9 +124,7 @@ export class PublicKey {
|
|
|
121
124
|
Buffer.from(seed),
|
|
122
125
|
programId.toBuffer(),
|
|
123
126
|
])
|
|
124
|
-
const hash = createHash('sha256')
|
|
125
|
-
.update(buffer)
|
|
126
|
-
.digest('hex')
|
|
127
|
+
const hash = createHash('sha256').update(buffer).digest('hex')
|
|
127
128
|
return new PublicKey(Buffer.from(hash, 'hex'))
|
|
128
129
|
}
|
|
129
130
|
|
|
@@ -132,20 +133,20 @@ export class PublicKey {
|
|
|
132
133
|
*/
|
|
133
134
|
static createProgramAddress(seeds, programId) {
|
|
134
135
|
let buffer = Buffer.alloc(0)
|
|
135
|
-
seeds.forEach(function(seed) {
|
|
136
|
+
seeds.forEach(function (seed) {
|
|
136
137
|
if (seed.length > MAX_SEED_LENGTH) {
|
|
137
138
|
throw new Error('Max seed length exceeded')
|
|
138
139
|
}
|
|
140
|
+
|
|
139
141
|
buffer = Buffer.concat([buffer, Buffer.from(seed)])
|
|
140
142
|
})
|
|
141
143
|
buffer = Buffer.concat([buffer, programId.toBuffer(), Buffer.from('ProgramDerivedAddress')])
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
.digest('hex')
|
|
145
|
-
let publicKeyBytes = new BN(hash, 16).toArray(null, 32)
|
|
144
|
+
const hash = createHash('sha256').update(buffer).digest('hex')
|
|
145
|
+
const publicKeyBytes = new BN(hash, 16).toArray(null, 32)
|
|
146
146
|
if (isOnCurve(publicKeyBytes)) {
|
|
147
147
|
throw new Error('Invalid seeds, address must fall off the curve')
|
|
148
148
|
}
|
|
149
|
+
|
|
149
150
|
return new PublicKey(publicKeyBytes)
|
|
150
151
|
}
|
|
151
152
|
}
|
|
@@ -154,15 +155,15 @@ export class PublicKey {
|
|
|
154
155
|
// This function and its dependents were sourced from:
|
|
155
156
|
// https://github.com/dchest/tweetnacl-js/blob/f1ec050ceae0861f34280e62498b1d3ed9c350c6/nacl.js#L792
|
|
156
157
|
function isOnCurve(p) {
|
|
157
|
-
|
|
158
|
+
const r = [naclLowLevel.gf(), naclLowLevel.gf(), naclLowLevel.gf(), naclLowLevel.gf()]
|
|
158
159
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
160
|
+
const t = naclLowLevel.gf()
|
|
161
|
+
const chk = naclLowLevel.gf()
|
|
162
|
+
const num = naclLowLevel.gf()
|
|
163
|
+
const den = naclLowLevel.gf()
|
|
164
|
+
const den2 = naclLowLevel.gf()
|
|
165
|
+
const den4 = naclLowLevel.gf()
|
|
166
|
+
const den6 = naclLowLevel.gf()
|
|
166
167
|
|
|
167
168
|
naclLowLevel.set25519(r[2], gf1)
|
|
168
169
|
naclLowLevel.unpack25519(r[1], p)
|
|
@@ -193,24 +194,10 @@ function isOnCurve(p) {
|
|
|
193
194
|
return 1
|
|
194
195
|
}
|
|
195
196
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
0x1b27,
|
|
201
|
-
0xc4ee,
|
|
202
|
-
0xe478,
|
|
203
|
-
0xad2f,
|
|
204
|
-
0x1806,
|
|
205
|
-
0x2f43,
|
|
206
|
-
0xd7a7,
|
|
207
|
-
0x3dfb,
|
|
208
|
-
0x0099,
|
|
209
|
-
0x2b4d,
|
|
210
|
-
0xdf0b,
|
|
211
|
-
0x4fc1,
|
|
212
|
-
0x2480,
|
|
213
|
-
0x2b83,
|
|
197
|
+
const gf1 = naclLowLevel.gf([1])
|
|
198
|
+
const I = naclLowLevel.gf([
|
|
199
|
+
0xa0_b0, 0x4a_0e, 0x1b_27, 0xc4_ee, 0xe4_78, 0xad_2f, 0x18_06, 0x2f_43, 0xd7_a7, 0x3d_fb, 0x00_99,
|
|
200
|
+
0x2b_4d, 0xdf_0b, 0x4f_c1, 0x24_80, 0x2b_83,
|
|
214
201
|
])
|
|
215
202
|
|
|
216
203
|
function neq25519(a, b) {
|
|
@@ -176,11 +176,11 @@ export const STAKE_INSTRUCTION_LAYOUTS = Object.freeze({
|
|
|
176
176
|
/**
|
|
177
177
|
* Stake Instruction class
|
|
178
178
|
*/
|
|
179
|
-
export
|
|
179
|
+
export const StakeInstruction = {
|
|
180
180
|
/**
|
|
181
181
|
* Decode a stake instruction and retrieve the instruction type.
|
|
182
182
|
*/
|
|
183
|
-
|
|
183
|
+
decodeInstructionType(instruction) {
|
|
184
184
|
this.checkProgramId(instruction.programId)
|
|
185
185
|
|
|
186
186
|
const instructionTypeLayout = BufferLayout.u32('instruction')
|
|
@@ -198,12 +198,12 @@ export class StakeInstruction {
|
|
|
198
198
|
}
|
|
199
199
|
|
|
200
200
|
return type
|
|
201
|
-
}
|
|
201
|
+
},
|
|
202
202
|
|
|
203
203
|
/**
|
|
204
204
|
* Decode a initialize stake instruction and retrieve the instruction params.
|
|
205
205
|
*/
|
|
206
|
-
|
|
206
|
+
decodeInitialize(instruction) {
|
|
207
207
|
this.checkProgramId(instruction.programId)
|
|
208
208
|
this.checkKeyLength(instruction.keys, 2)
|
|
209
209
|
|
|
@@ -220,12 +220,12 @@ export class StakeInstruction {
|
|
|
220
220
|
),
|
|
221
221
|
lockup: new Lockup(lockup.unixTimestamp, lockup.epoch, new PublicKey(lockup.custodian)),
|
|
222
222
|
}
|
|
223
|
-
}
|
|
223
|
+
},
|
|
224
224
|
|
|
225
225
|
/**
|
|
226
226
|
* Decode a delegate stake instruction and retrieve the instruction params.
|
|
227
227
|
*/
|
|
228
|
-
|
|
228
|
+
decodeDelegate(instruction) {
|
|
229
229
|
this.checkProgramId(instruction.programId)
|
|
230
230
|
this.checkKeyLength(instruction.keys, 6)
|
|
231
231
|
decodeData(STAKE_INSTRUCTION_LAYOUTS.Delegate, instruction.data)
|
|
@@ -235,12 +235,12 @@ export class StakeInstruction {
|
|
|
235
235
|
votePubkey: instruction.keys[1].pubkey,
|
|
236
236
|
authorizedPubkey: instruction.keys[5].pubkey,
|
|
237
237
|
}
|
|
238
|
-
}
|
|
238
|
+
},
|
|
239
239
|
|
|
240
240
|
/**
|
|
241
241
|
* Decode a withdraw stake instruction and retrieve the instruction params.
|
|
242
242
|
*/
|
|
243
|
-
|
|
243
|
+
decodeWithdraw(instruction) {
|
|
244
244
|
this.checkProgramId(instruction.programId)
|
|
245
245
|
this.checkKeyLength(instruction.keys, 5)
|
|
246
246
|
const { lamports } = decodeData(STAKE_INSTRUCTION_LAYOUTS.Withdraw, instruction.data)
|
|
@@ -251,12 +251,12 @@ export class StakeInstruction {
|
|
|
251
251
|
authorizedPubkey: instruction.keys[4].pubkey,
|
|
252
252
|
lamports,
|
|
253
253
|
}
|
|
254
|
-
}
|
|
254
|
+
},
|
|
255
255
|
|
|
256
256
|
/**
|
|
257
257
|
* Decode a deactivate stake instruction and retrieve the instruction params.
|
|
258
258
|
*/
|
|
259
|
-
|
|
259
|
+
decodeDeactivate(instruction) {
|
|
260
260
|
this.checkProgramId(instruction.programId)
|
|
261
261
|
this.checkKeyLength(instruction.keys, 3)
|
|
262
262
|
decodeData(STAKE_INSTRUCTION_LAYOUTS.Deactivate, instruction.data)
|
|
@@ -265,27 +265,27 @@ export class StakeInstruction {
|
|
|
265
265
|
stakePubkey: instruction.keys[0].pubkey,
|
|
266
266
|
authorizedPubkey: instruction.keys[2].pubkey,
|
|
267
267
|
}
|
|
268
|
-
}
|
|
268
|
+
},
|
|
269
269
|
|
|
270
270
|
/**
|
|
271
271
|
* @private
|
|
272
272
|
*/
|
|
273
|
-
|
|
273
|
+
checkProgramId(programId) {
|
|
274
274
|
if (!programId.equals(StakeProgram.programId)) {
|
|
275
275
|
throw new Error('invalid instruction; programId is not StakeProgram')
|
|
276
276
|
}
|
|
277
|
-
}
|
|
277
|
+
},
|
|
278
278
|
|
|
279
279
|
/**
|
|
280
280
|
* @private
|
|
281
281
|
*/
|
|
282
|
-
|
|
282
|
+
checkKeyLength(keys, expectedLength) {
|
|
283
283
|
if (keys.length < expectedLength) {
|
|
284
284
|
throw new Error(
|
|
285
285
|
`invalid instruction; found ${keys.length} keys, expected at least ${expectedLength}`
|
|
286
286
|
)
|
|
287
287
|
}
|
|
288
|
-
}
|
|
288
|
+
},
|
|
289
289
|
}
|
|
290
290
|
|
|
291
291
|
/**
|
|
@@ -303,13 +303,13 @@ export const StakeAuthorizationLayout = Object.freeze({
|
|
|
303
303
|
/**
|
|
304
304
|
* Factory class for transactions to interact with the Stake program
|
|
305
305
|
*/
|
|
306
|
-
export
|
|
306
|
+
export const StakeProgram = {
|
|
307
307
|
/**
|
|
308
308
|
* Public key that identifies the Stake program
|
|
309
309
|
*/
|
|
310
|
-
|
|
310
|
+
get programId() {
|
|
311
311
|
return new PublicKey('Stake11111111111111111111111111111111111111')
|
|
312
|
-
}
|
|
312
|
+
},
|
|
313
313
|
|
|
314
314
|
/**
|
|
315
315
|
* Max space of a Stake account
|
|
@@ -318,14 +318,14 @@ export class StakeProgram {
|
|
|
318
318
|
* `std::mem::size_of::<StakeState>()`:
|
|
319
319
|
* https://docs.rs/solana-stake-program/1.4.4/solana_stake_program/stake_state/enum.StakeState.html
|
|
320
320
|
*/
|
|
321
|
-
|
|
321
|
+
get space() {
|
|
322
322
|
return 200
|
|
323
|
-
}
|
|
323
|
+
},
|
|
324
324
|
|
|
325
325
|
/**
|
|
326
326
|
* Generate an Initialize instruction to add to a Stake Create transaction
|
|
327
327
|
*/
|
|
328
|
-
|
|
328
|
+
initialize(params) {
|
|
329
329
|
const { stakePubkey, authorized, lockup } = params
|
|
330
330
|
const type = STAKE_INSTRUCTION_LAYOUTS.Initialize
|
|
331
331
|
const data = encodeData(type, {
|
|
@@ -348,13 +348,13 @@ export class StakeProgram {
|
|
|
348
348
|
data,
|
|
349
349
|
}
|
|
350
350
|
return new TransactionInstruction(instructionData)
|
|
351
|
-
}
|
|
351
|
+
},
|
|
352
352
|
|
|
353
353
|
/**
|
|
354
354
|
* Generate a Transaction that creates a new Stake account at
|
|
355
355
|
* an address generated with `from`, a seed, and the Stake programId
|
|
356
356
|
*/
|
|
357
|
-
|
|
357
|
+
createAccountWithSeed(params) {
|
|
358
358
|
const transaction = new Transaction()
|
|
359
359
|
transaction.add(
|
|
360
360
|
SystemProgram.createAccountWithSeed({
|
|
@@ -370,12 +370,12 @@ export class StakeProgram {
|
|
|
370
370
|
|
|
371
371
|
const { stakePubkey, authorized, lockup } = params
|
|
372
372
|
return transaction.add(this.initialize({ stakePubkey, authorized, lockup }))
|
|
373
|
-
}
|
|
373
|
+
},
|
|
374
374
|
|
|
375
375
|
/**
|
|
376
376
|
* Generate a Transaction that creates a new Stake account
|
|
377
377
|
*/
|
|
378
|
-
|
|
378
|
+
createAccount(params) {
|
|
379
379
|
const transaction = new Transaction()
|
|
380
380
|
transaction.add(
|
|
381
381
|
SystemProgram.createAccount({
|
|
@@ -389,14 +389,14 @@ export class StakeProgram {
|
|
|
389
389
|
|
|
390
390
|
const { stakePubkey, authorized, lockup } = params
|
|
391
391
|
return transaction.add(this.initialize({ stakePubkey, authorized, lockup }))
|
|
392
|
-
}
|
|
392
|
+
},
|
|
393
393
|
|
|
394
394
|
/**
|
|
395
395
|
* Generate a Transaction that delegates Stake tokens to a validator
|
|
396
396
|
* Vote PublicKey. This transaction can also be used to redelegate Stake
|
|
397
397
|
* to a new validator Vote PublicKey.
|
|
398
398
|
*/
|
|
399
|
-
|
|
399
|
+
delegate(params) {
|
|
400
400
|
const { stakePubkey, authorizedPubkey, votePubkey } = params
|
|
401
401
|
|
|
402
402
|
const type = STAKE_INSTRUCTION_LAYOUTS.Delegate
|
|
@@ -418,12 +418,12 @@ export class StakeProgram {
|
|
|
418
418
|
programId: this.programId,
|
|
419
419
|
data,
|
|
420
420
|
})
|
|
421
|
-
}
|
|
421
|
+
},
|
|
422
422
|
|
|
423
423
|
/**
|
|
424
424
|
* Generate a Transaction that withdraws deactivated Stake tokens.
|
|
425
425
|
*/
|
|
426
|
-
|
|
426
|
+
withdraw(params) {
|
|
427
427
|
const { stakePubkey, authorizedPubkey, toPubkey, lamports } = params
|
|
428
428
|
const type = STAKE_INSTRUCTION_LAYOUTS.Withdraw
|
|
429
429
|
const data = encodeData(type, { lamports })
|
|
@@ -443,12 +443,12 @@ export class StakeProgram {
|
|
|
443
443
|
programId: this.programId,
|
|
444
444
|
data,
|
|
445
445
|
})
|
|
446
|
-
}
|
|
446
|
+
},
|
|
447
447
|
|
|
448
448
|
/**
|
|
449
449
|
* Generate a Transaction that deactivates Stake tokens.
|
|
450
450
|
*/
|
|
451
|
-
|
|
451
|
+
deactivate(params) {
|
|
452
452
|
const { stakePubkey, authorizedPubkey } = params
|
|
453
453
|
const type = STAKE_INSTRUCTION_LAYOUTS.Deactivate
|
|
454
454
|
const data = encodeData(type)
|
|
@@ -462,5 +462,5 @@ export class StakeProgram {
|
|
|
462
462
|
programId: this.programId,
|
|
463
463
|
data,
|
|
464
464
|
})
|
|
465
|
-
}
|
|
465
|
+
},
|
|
466
466
|
}
|