@exodus/solana-lib 1.7.4 → 1.7.6

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.7.4",
3
+ "version": "1.7.6",
4
4
  "description": "Exodus internal Solana low-level library",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -12,20 +12,27 @@
12
12
  "publishConfig": {
13
13
  "access": "restricted"
14
14
  },
15
+ "scripts": {
16
+ "test": "run -T jest",
17
+ "lint": "run -T eslint ./src",
18
+ "lint:fix": "yarn lint --fix"
19
+ },
15
20
  "dependencies": {
16
21
  "@exodus/asset-lib": "^3.7.1",
17
22
  "@exodus/buffer-layout": "^1.2.0-exodus1",
18
23
  "@exodus/key-utils": "^3.1.0",
19
24
  "@exodus/models": "^10.1.0",
20
- "@exodus/solana-meta": "^1.0.5",
21
- "@exodus/solana-spl-token": "0.1.8-exodus.1",
25
+ "@exodus/solana-meta": "^1.0.7",
22
26
  "@project-serum/serum": "0.13.64",
23
27
  "bn.js": "^4.11.0",
24
28
  "borsh": "^0.7.0",
25
29
  "bs58": "^4.0.1",
26
30
  "create-hash": "^1.1.3",
27
31
  "lodash": "^4.17.11",
32
+ "minimalistic-assert": "^1.0.1",
28
33
  "tweetnacl": "^1.0.3"
29
34
  },
30
- "gitHead": "88be13b711bcb6ca1be86993d67e69d4ec5ac263"
35
+ "devDependencies": {
36
+ "@solana/web3.js": "^1.90.0"
37
+ }
31
38
  }
package/src/constants.js CHANGED
@@ -25,7 +25,7 @@ export const SYSVAR_INSTRUCTIONS_PUBKEY = new PublicKey(
25
25
 
26
26
  export const SEED = 'stake:0'
27
27
 
28
- export const LAMPORTS_PER_SOL = 1000000000
28
+ export const LAMPORTS_PER_SOL = 1_000_000_000
29
29
 
30
30
  export const SOL_DECIMAL = Math.log10(LAMPORTS_PER_SOL)
31
31
 
package/src/encode.js CHANGED
@@ -12,21 +12,6 @@ import BN from 'bn.js'
12
12
  import { Metadata, METADATA_SCHEMA } from './helpers/metadata-schema'
13
13
  import { deserializeUnchecked } from 'borsh'
14
14
 
15
- /*
16
- const { BinaryReader, BinaryWriter, deserializeUnchecked } = require('borsh')
17
-
18
- BinaryReader.prototype.readPubkeyAsString = function () {
19
- const reader = this
20
- const array = reader.readFixedArray(32)
21
- return bs58.encode(array)
22
- }
23
-
24
- BinaryWriter.prototype.writePubkeyAsString = function (value) {
25
- const writer = this
26
- writer.writeFixedArray(bs58.decode(value))
27
- }
28
- */
29
-
30
15
  export function getAddressFromPublicKey(publicKey) {
31
16
  return bs58.encode(Buffer.from(publicKey, 'hex'))
32
17
  }
@@ -42,12 +27,10 @@ export function isValidAddress(address) {
42
27
  if (decoded.length !== 32) {
43
28
  return false
44
29
  }
30
+
45
31
  const _bn = new BN(decoded)
46
- if (_bn.byteLength() > 32) {
47
- return false
48
- }
49
- return true
50
- } catch (e) {
32
+ return _bn.byteLength() <= 32
33
+ } catch {
51
34
  return false
52
35
  }
53
36
  }
@@ -3,15 +3,13 @@
3
3
  import bs58 from 'bs58'
4
4
  import { BinaryReader, BinaryWriter } from 'borsh'
5
5
 
6
- BinaryReader.prototype.readPubkeyAsString = function() {
7
- const reader = this
8
- const array = reader.readFixedArray(32)
6
+ BinaryReader.prototype.readPubkeyAsString = function () {
7
+ const array = this.readFixedArray(32)
9
8
  return bs58.encode(array)
10
9
  }
11
10
 
12
- BinaryWriter.prototype.writePubkeyAsString = function(value) {
13
- const writer = this
14
- writer.writeFixedArray(bs58.decode(value))
11
+ BinaryWriter.prototype.writePubkeyAsString = function (value) {
12
+ this.writeFixedArray(bs58.decode(value))
15
13
  }
16
14
 
17
15
  class Data {
@@ -8,7 +8,7 @@ import {
8
8
  TOKEN_PROGRAM_ID,
9
9
  } from '../constants'
10
10
 
11
- import { ASSOCIATED_TOKEN_PROGRAM_ID } from '@solana/spl-token'
11
+ import { ASSOCIATED_TOKEN_PROGRAM_ID } from './spl-token'
12
12
  import {
13
13
  findAssociatedTokenAddress,
14
14
  getMasterEditionPDA,
@@ -1,11 +1,16 @@
1
1
  import assert from 'assert'
2
2
  import BN from 'bn.js'
3
3
  import * as BufferLayout from '@exodus/buffer-layout'
4
- import { TransactionInstruction } from '../vendor'
4
+ import { PublicKey, SYSVAR_RENT_PUBKEY, SystemProgram, TransactionInstruction } from '../vendor'
5
5
  import * as Layout from '../vendor/utils/layout'
6
6
 
7
7
  // Extracted from https://github.com/ExodusMovement/solana-spl-token/blob/master/src/index.js#L263
8
8
 
9
+ export const ASSOCIATED_TOKEN_PROGRAM_ID = new PublicKey(
10
+ 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL'
11
+ )
12
+ export const TOKEN_PROGRAM_ID = new PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA')
13
+
9
14
  /**
10
15
  * 64-bit value
11
16
  */
@@ -19,6 +24,7 @@ export class U64 extends BN {
19
24
  if (b.length === 8) {
20
25
  return b
21
26
  }
27
+
22
28
  assert(b.length < 8, 'u64 too large')
23
29
 
24
30
  const zeroPad = Buffer.alloc(8)
@@ -55,10 +61,406 @@ const uint64 = (property = 'uint64') => {
55
61
  return BufferLayout.blob(8, property)
56
62
  }
57
63
 
64
+ /**
65
+ * Unfortunately, BufferLayout.encode uses an `instanceof` check for `Buffer`
66
+ * which fails when using `publicKey.toBuffer()` directly because the bundled `Buffer`
67
+ * class in `@solana/web3.js` is different from the bundled `Buffer` class in this package
68
+ */
69
+ const pubkeyToBuffer = (publicKey) => {
70
+ return Buffer.from(publicKey.toBuffer())
71
+ }
72
+
58
73
  /**
59
74
  * An ERC20-like Token
60
75
  */
61
- export class Token {
76
+ export const Token = {
77
+ /**
78
+ * Construct an Approve instruction
79
+ *
80
+ * @param programId SPL Token program account
81
+ * @param account Public key of the account
82
+ * @param delegate Account authorized to perform a transfer of tokens from the source account
83
+ * @param owner Owner of the source account
84
+ * @param multiSigners Signing accounts if `owner` is a multiSig
85
+ * @param amount Maximum number of tokens the delegate may transfer
86
+ */
87
+ createApproveInstruction(programId, account, delegate, owner, multiSigners, amount) {
88
+ const dataLayout = BufferLayout.struct([BufferLayout.u8('instruction'), uint64('amount')])
89
+ const data = Buffer.alloc(dataLayout.span)
90
+
91
+ dataLayout.encode(
92
+ {
93
+ instruction: 4, // Approve instruction
94
+ amount: new U64(amount).toBuffer(),
95
+ },
96
+ data
97
+ )
98
+
99
+ const keys = [
100
+ {
101
+ pubkey: account,
102
+ isSigner: false,
103
+ isWritable: true,
104
+ },
105
+ {
106
+ pubkey: delegate,
107
+ isSigner: false,
108
+ isWritable: false,
109
+ },
110
+ ]
111
+
112
+ if (multiSigners.length === 0) {
113
+ keys.push({
114
+ pubkey: owner,
115
+ isSigner: true,
116
+ isWritable: false,
117
+ })
118
+ } else {
119
+ keys.push({
120
+ pubkey: owner,
121
+ isSigner: false,
122
+ isWritable: false,
123
+ })
124
+
125
+ multiSigners.forEach((signer) =>
126
+ keys.push({
127
+ pubkey: signer.publicKey,
128
+ isSigner: true,
129
+ isWritable: false,
130
+ })
131
+ )
132
+ }
133
+
134
+ return new TransactionInstruction({
135
+ keys,
136
+ programId,
137
+ data,
138
+ })
139
+ },
140
+
141
+ /**
142
+ * Construct the AssociatedTokenProgram instruction to create the associated
143
+ * token account
144
+ *
145
+ * @param associatedProgramId SPL Associated Token program account
146
+ * @param programId SPL Token program account
147
+ * @param mint Token mint account
148
+ * @param associatedAccount New associated account
149
+ * @param owner Owner of the new account
150
+ * @param payer Payer of fees
151
+ */
152
+ createAssociatedTokenAccountInstruction(
153
+ associatedProgramId,
154
+ programId,
155
+ mint,
156
+ associatedAccount,
157
+ owner,
158
+ payer
159
+ ) {
160
+ const data = Buffer.alloc(0)
161
+
162
+ const keys = [
163
+ {
164
+ pubkey: payer,
165
+ isSigner: true,
166
+ isWritable: true,
167
+ },
168
+ {
169
+ pubkey: associatedAccount,
170
+ isSigner: false,
171
+ isWritable: true,
172
+ },
173
+ {
174
+ pubkey: owner,
175
+ isSigner: false,
176
+ isWritable: false,
177
+ },
178
+ {
179
+ pubkey: mint,
180
+ isSigner: false,
181
+ isWritable: false,
182
+ },
183
+ {
184
+ pubkey: SystemProgram.programId,
185
+ isSigner: false,
186
+ isWritable: false,
187
+ },
188
+ {
189
+ pubkey: programId,
190
+ isSigner: false,
191
+ isWritable: false,
192
+ },
193
+ {
194
+ pubkey: SYSVAR_RENT_PUBKEY,
195
+ isSigner: false,
196
+ isWritable: false,
197
+ },
198
+ ]
199
+
200
+ return new TransactionInstruction({
201
+ keys,
202
+ programId: associatedProgramId,
203
+ data,
204
+ })
205
+ },
206
+
207
+ /**
208
+ * Construct a Close instruction
209
+ *
210
+ * @param programId SPL Token program account
211
+ * @param account Account to close
212
+ * @param dest Account to receive the remaining balance of the closed account
213
+ * @param authority Account Close authority
214
+ * @param multiSigners Signing accounts if `owner` is a multiSig
215
+ */
216
+ createCloseAccountInstruction(programId, account, dest, owner, multiSigners) {
217
+ const dataLayout = BufferLayout.struct([BufferLayout.u8('instruction')])
218
+ const data = Buffer.alloc(dataLayout.span)
219
+
220
+ dataLayout.encode(
221
+ {
222
+ instruction: 9, // CloseAccount instruction
223
+ },
224
+ data
225
+ )
226
+
227
+ const keys = [
228
+ {
229
+ pubkey: account,
230
+ isSigner: false,
231
+ isWritable: true,
232
+ },
233
+ {
234
+ pubkey: dest,
235
+ isSigner: false,
236
+ isWritable: true,
237
+ },
238
+ ]
239
+
240
+ if (multiSigners.length === 0) {
241
+ keys.push({
242
+ pubkey: owner,
243
+ isSigner: true,
244
+ isWritable: false,
245
+ })
246
+ } else {
247
+ keys.push({
248
+ pubkey: owner,
249
+ isSigner: false,
250
+ isWritable: false,
251
+ })
252
+ multiSigners.forEach((signer) =>
253
+ keys.push({
254
+ pubkey: signer.publicKey,
255
+ isSigner: true,
256
+ isWritable: false,
257
+ })
258
+ )
259
+ }
260
+
261
+ return new TransactionInstruction({
262
+ keys,
263
+ programId,
264
+ data,
265
+ })
266
+ },
267
+
268
+ /**
269
+ * Construct an InitializeAccount instruction
270
+ *
271
+ * @param programId SPL Token program account
272
+ * @param mint Token mint account
273
+ * @param account New account
274
+ * @param owner Owner of the new account
275
+ */
276
+ createInitAccountInstruction(programId, mint, account, owner) {
277
+ const dataLayout = BufferLayout.struct([BufferLayout.u8('instruction')])
278
+ const data = Buffer.alloc(dataLayout.span)
279
+
280
+ dataLayout.encode(
281
+ {
282
+ instruction: 1, // InitializeAccount instruction
283
+ },
284
+ data
285
+ )
286
+
287
+ const keys = [
288
+ {
289
+ pubkey: account,
290
+ isSigner: false,
291
+ isWritable: true,
292
+ },
293
+ {
294
+ pubkey: mint,
295
+ isSigner: false,
296
+ isWritable: false,
297
+ },
298
+ {
299
+ pubkey: owner,
300
+ isSigner: false,
301
+ isWritable: false,
302
+ },
303
+ {
304
+ pubkey: SYSVAR_RENT_PUBKEY,
305
+ isSigner: false,
306
+ isWritable: false,
307
+ },
308
+ ]
309
+
310
+ return new TransactionInstruction({
311
+ keys,
312
+ programId,
313
+ data,
314
+ })
315
+ },
316
+
317
+ /**
318
+ * Construct an InitializeMint instruction
319
+ *
320
+ * @param programId SPL Token program account
321
+ * @param mint Token mint account
322
+ * @param decimals Number of decimals in token account amounts
323
+ * @param mintAuthority Minting authority
324
+ * @param freezeAuthority Optional authority that can freeze token accounts
325
+ */
326
+ createInitMintInstruction(programId, mint, decimals, mintAuthority, freezeAuthority) {
327
+ const dataLayout = BufferLayout.struct([
328
+ BufferLayout.u8('instruction'),
329
+ BufferLayout.u8('decimals'),
330
+ publicKey('mintAuthority'),
331
+ BufferLayout.u8('option'),
332
+ publicKey('freezeAuthority'),
333
+ ])
334
+
335
+ let data = Buffer.alloc(1024)
336
+ const encodeLength = dataLayout.encode(
337
+ {
338
+ instruction: 0, // InitializeMint instruction
339
+ decimals,
340
+ mintAuthority: pubkeyToBuffer(mintAuthority),
341
+ option: freezeAuthority === null ? 0 : 1,
342
+ freezeAuthority: pubkeyToBuffer(freezeAuthority || new PublicKey(0)),
343
+ },
344
+ data
345
+ )
346
+ data = data.slice(0, encodeLength)
347
+
348
+ const keys = [
349
+ {
350
+ pubkey: mint,
351
+ isSigner: false,
352
+ isWritable: true,
353
+ },
354
+ {
355
+ pubkey: SYSVAR_RENT_PUBKEY,
356
+ isSigner: false,
357
+ isWritable: false,
358
+ },
359
+ ]
360
+
361
+ return new TransactionInstruction({
362
+ keys,
363
+ programId,
364
+ data,
365
+ })
366
+ },
367
+
368
+ /**
369
+ * Construct a MintTo instruction
370
+ *
371
+ * @param programId SPL Token program account
372
+ * @param mint Public key of the mint
373
+ * @param dest Public key of the account to mint to
374
+ * @param authority The mint authority
375
+ * @param multiSigners Signing accounts if `authority` is a multiSig
376
+ * @param amount Amount to mint
377
+ */
378
+ createMintToInstruction(programId, mint, dest, authority, multiSigners, amount) {
379
+ const dataLayout = BufferLayout.struct([BufferLayout.u8('instruction'), uint64('amount')])
380
+ const data = Buffer.alloc(dataLayout.span)
381
+
382
+ dataLayout.encode(
383
+ {
384
+ instruction: 7, // MintTo instruction
385
+ amount: new U64(amount).toBuffer(),
386
+ },
387
+ data
388
+ )
389
+
390
+ const keys = [
391
+ {
392
+ pubkey: mint,
393
+ isSigner: false,
394
+ isWritable: true,
395
+ },
396
+ {
397
+ pubkey: dest,
398
+ isSigner: false,
399
+ isWritable: true,
400
+ },
401
+ ]
402
+
403
+ if (multiSigners.length === 0) {
404
+ keys.push({
405
+ pubkey: authority,
406
+ isSigner: true,
407
+ isWritable: false,
408
+ })
409
+ } else {
410
+ keys.push({
411
+ pubkey: authority,
412
+ isSigner: false,
413
+ isWritable: false,
414
+ })
415
+
416
+ multiSigners.forEach((signer) =>
417
+ keys.push({
418
+ pubkey: signer.publicKey,
419
+ isSigner: true,
420
+ isWritable: false,
421
+ })
422
+ )
423
+ }
424
+
425
+ return new TransactionInstruction({
426
+ keys,
427
+ programId,
428
+ data,
429
+ })
430
+ },
431
+
432
+ /**
433
+ * Construct a SyncNative instruction
434
+ *
435
+ * @param programId SPL Token program account
436
+ * @param nativeAccount Account to sync lamports from
437
+ */
438
+ createSyncNativeInstruction(programId, nativeAccount) {
439
+ const dataLayout = BufferLayout.struct([BufferLayout.u8('instruction')])
440
+ const data = Buffer.alloc(dataLayout.span)
441
+
442
+ dataLayout.encode(
443
+ {
444
+ instruction: 17, // SyncNative instruction
445
+ },
446
+ data
447
+ )
448
+
449
+ const keys = [
450
+ {
451
+ pubkey: nativeAccount,
452
+ isSigner: false,
453
+ isWritable: true,
454
+ },
455
+ ]
456
+
457
+ return new TransactionInstruction({
458
+ keys,
459
+ programId,
460
+ data,
461
+ })
462
+ },
463
+
62
464
  /**
63
465
  * Construct a Transfer instruction
64
466
  *
@@ -69,7 +471,7 @@ export class Token {
69
471
  * @param multiSigners Signing accounts if `authority` is a multiSig
70
472
  * @param amount Number of tokens to transfer
71
473
  */
72
- static createTransferInstruction(programId, source, destination, owner, multiSigners, amount) {
474
+ createTransferInstruction(programId, source, destination, owner, multiSigners, amount) {
73
475
  const dataLayout = BufferLayout.struct([
74
476
  BufferLayout.u8('instruction'),
75
477
  Layout.uint64('amount'),
@@ -84,7 +486,7 @@ export class Token {
84
486
  data
85
487
  )
86
488
 
87
- let keys = [
489
+ const keys = [
88
490
  { pubkey: source, isSigner: false, isWritable: true },
89
491
  { pubkey: destination, isSigner: false, isWritable: true },
90
492
  ]
@@ -104,14 +506,15 @@ export class Token {
104
506
  })
105
507
  )
106
508
  }
509
+
107
510
  return new TransactionInstruction({
108
511
  keys,
109
- programId: programId,
512
+ programId,
110
513
  data,
111
514
  })
112
- }
515
+ },
113
516
 
114
- static decode(data) {
517
+ decode(data) {
115
518
  return BufferLayout.struct([
116
519
  publicKey('mint'),
117
520
  publicKey('owner'),
@@ -125,5 +528,5 @@ export class Token {
125
528
  BufferLayout.u32('closeAuthorityOption'),
126
529
  publicKey('closeAuthority'),
127
530
  ]).decode(data)
128
- }
531
+ },
129
532
  }
@@ -1,4 +1,4 @@
1
- import { Token } from '@exodus/solana-spl-token'
1
+ import { Token } from './spl-token'
2
2
  import { PublicKey, TransactionInstruction, SystemProgram, SYSVAR_RENT_PUBKEY } from '../vendor'
3
3
  import { SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID, TOKEN_PROGRAM_ID } from '../constants'
4
4
  import { findAssociatedTokenAddress } from '../encode'
@@ -17,14 +17,12 @@ export const createAssociatedTokenAccount = (
17
17
  const ownerPublicKey = new PublicKey(ownerAddress)
18
18
  const tokenMintPublicKey = new PublicKey(tokenMintAddress)
19
19
 
20
- const ix = createIx(
20
+ return createIx(
21
21
  feePayerPublicKey, // feePayer
22
22
  associatedTokenAccountPublicKey,
23
23
  ownerPublicKey,
24
24
  tokenMintPublicKey
25
- )
26
-
27
- return ix // returns the instruction
25
+ ) // returns the instruction
28
26
  }
29
27
 
30
28
  function createIx(
@@ -59,7 +57,7 @@ export const createTokenTransferInstruction = (owner, fromTokenAddress, to, amou
59
57
  console.log(`destination token address: ${destinationPubkey.toBase58()}`)
60
58
  const ownerAccountOrWalletPublicKey = new PublicKey(owner) // the only native SOL address
61
59
 
62
- const transferIx = Token.createTransferInstruction(
60
+ return Token.createTransferInstruction(
63
61
  TOKEN_PROGRAM_ID,
64
62
  sourcePubkey,
65
63
  destinationPubkey,
@@ -67,8 +65,6 @@ export const createTokenTransferInstruction = (owner, fromTokenAddress, to, amou
67
65
  [],
68
66
  amount
69
67
  )
70
-
71
- return transferIx
72
68
  }
73
69
 
74
70
  export const createCloseAccountInstruction = ({
package/src/index.js CHANGED
@@ -11,5 +11,5 @@ export {
11
11
  SystemProgram,
12
12
  } from './vendor'
13
13
  export { default as Transaction } from './transaction'
14
- export { U64 } from './helpers/spl-token'
14
+ export { U64, Token } from './helpers/spl-token'
15
15
  export { createGetKeyIdentifier, getSupportedPurposes } from './key-identifier'