@exodus/solana-lib 3.2.0 → 3.2.2

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": "3.2.0",
3
+ "version": "3.2.2",
4
4
  "description": "Exodus internal Solana low-level library",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -25,7 +25,7 @@
25
25
  "@exodus/models": "^10.1.0",
26
26
  "@exodus/project-serum-serum": "0.13.64-exodus.0",
27
27
  "@exodus/solana-web3.js": "^1.63.1-exodus.3",
28
- "bn.js": "^4.11.0",
28
+ "bn.js": "^5.2.1",
29
29
  "borsh": "^0.7.0",
30
30
  "bs58": "^4.0.1",
31
31
  "create-hash": "^1.1.3",
@@ -40,5 +40,5 @@
40
40
  "@solana/web3.js": "^1.90.0",
41
41
  "bip39": "^2.6.0"
42
42
  },
43
- "gitHead": "7fa370d0fdd120110c54d56e2b528a5464e6f9e5"
43
+ "gitHead": "8f0211c5cbdc7117872f2f910c9b31d7e4e106f0"
44
44
  }
@@ -7,7 +7,7 @@ import {
7
7
  export const getSupportedPurposes = () => [44]
8
8
 
9
9
  export const createGetKeyIdentifier =
10
- ({ bip44 } = {}) =>
10
+ ({ bip44, assetName } = {}) =>
11
11
  (partialParams = {}) => {
12
12
  assert(typeof bip44 === 'number', 'bip44 must be a number')
13
13
 
@@ -31,6 +31,7 @@ export const createGetKeyIdentifier =
31
31
  case 'phantom':
32
32
  // Phantom doesn't use chainIndex (normal vs change address)
33
33
  return {
34
+ assetName,
34
35
  derivationAlgorithm: 'SLIP10',
35
36
  derivationPath: `m/${purpose}'/${unhardenedBip44}'/${accountIndex}'/${addressIndex}'`,
36
37
  keyType: 'nacl',
@@ -38,17 +39,19 @@ export const createGetKeyIdentifier =
38
39
  case 'ledger':
39
40
  case 'trust':
40
41
  return {
42
+ assetName,
41
43
  derivationAlgorithm: 'SLIP10',
42
44
  derivationPath: `m/${purpose}'/${unhardenedBip44}'/${accountIndex}'`,
43
45
  keyType: 'nacl',
44
46
  }
45
47
  case 'mathwallet':
46
48
  return {
49
+ assetName,
47
50
  derivationAlgorithm: 'BIP32',
48
51
  derivationPath: `m/${purpose}'/${unhardenedBip44}'/${accountIndex}'/${addressIndex}`,
49
52
  keyType: 'nacl',
50
53
  }
51
54
  default:
52
- return _createGetKeyIdentifier({ bip44, keyType: 'nacl' })(params)
55
+ return _createGetKeyIdentifier({ bip44, keyType: 'nacl', assetName })(params)
53
56
  }
54
57
  }
@@ -412,7 +412,14 @@ class Tx {
412
412
  static decodeStakingTx(serialized) {
413
413
  // as base64
414
414
  const wireTransaction = Buffer.from(serialized, 'base64')
415
- const tx = Transaction.from(wireTransaction) // Transaction instance
415
+
416
+ let tx
417
+ try {
418
+ tx = Transaction.from(wireTransaction) // Transaction instance
419
+ } catch {
420
+ // versioned transaction
421
+ return null
422
+ }
416
423
 
417
424
  const txId = bs58.encode(tx.signature)
418
425
 
@@ -6,6 +6,7 @@ import { PublicKey } from './publickey'
6
6
  import * as Layout from './utils/layout'
7
7
  import { PACKET_DATA_SIZE } from './constants'
8
8
  import * as shortvec from './utils/shortvec-encoding'
9
+ import { guardedShift, guardedSplice } from './utils/guarded-array-utils.js'
9
10
 
10
11
  /**
11
12
  * The message header, identifying signed and read-only account
@@ -36,7 +37,8 @@ import * as shortvec from './utils/shortvec-encoding'
36
37
  * @property {CompiledInstruction[]} instructions Instructions that will be executed in sequence and committed in one atomic transaction if all succeed.
37
38
  */
38
39
 
39
- const PUBKEY_LENGTH = 32
40
+ const PUBLIC_KEY_LENGTH = 32
41
+ const VERSION_PREFIX_MASK = 0x7f
40
42
 
41
43
  /**
42
44
  * List of instructions to be processed atomically
@@ -155,36 +157,39 @@ export class Message {
155
157
  */
156
158
  static from(buffer) {
157
159
  // Slice up wire data
158
- let byteArray = [...buffer]
160
+ const byteArray = [...buffer]
159
161
 
160
- const numRequiredSignatures = byteArray.shift()
161
- const numReadonlySignedAccounts = byteArray.shift()
162
- const numReadonlyUnsignedAccounts = byteArray.shift()
162
+ const numRequiredSignatures = guardedShift(byteArray)
163
+ if (numRequiredSignatures !== (numRequiredSignatures & VERSION_PREFIX_MASK)) {
164
+ throw new Error('Versioned messages must be deserialized with VersionedMessage.deserialize()')
165
+ }
166
+
167
+ const numReadonlySignedAccounts = guardedShift(byteArray)
168
+ const numReadonlyUnsignedAccounts = guardedShift(byteArray)
163
169
 
164
170
  const accountCount = shortvec.decodeLength(byteArray)
165
171
  const accountKeys = []
166
172
  for (let i = 0; i < accountCount; i++) {
167
- const account = byteArray.slice(0, PUBKEY_LENGTH)
168
- byteArray = byteArray.slice(PUBKEY_LENGTH)
169
- accountKeys.push(bs58.encode(Buffer.from(account)))
173
+ const account = guardedSplice(byteArray, 0, PUBLIC_KEY_LENGTH)
174
+ accountKeys.push(Buffer.from(account))
170
175
  }
171
176
 
172
- const recentBlockhash = byteArray.slice(0, PUBKEY_LENGTH)
173
- byteArray = byteArray.slice(PUBKEY_LENGTH)
177
+ const recentBlockhash = guardedSplice(byteArray, 0, PUBLIC_KEY_LENGTH)
174
178
 
175
179
  const instructionCount = shortvec.decodeLength(byteArray)
176
180
  const instructions = []
177
181
  for (let i = 0; i < instructionCount; i++) {
178
- const instruction = Object.create(null)
179
- instruction.programIdIndex = byteArray.shift()
182
+ const programIdIndex = guardedShift(byteArray)
180
183
  const accountCount = shortvec.decodeLength(byteArray)
181
- instruction.accounts = byteArray.slice(0, accountCount)
182
- byteArray = byteArray.slice(accountCount)
184
+ const accounts = guardedSplice(byteArray, 0, accountCount)
183
185
  const dataLength = shortvec.decodeLength(byteArray)
184
- const data = byteArray.slice(0, dataLength)
185
- instruction.data = bs58.encode(Buffer.from(data))
186
- byteArray = byteArray.slice(dataLength)
187
- instructions.push(instruction)
186
+ const dataSlice = guardedSplice(byteArray, 0, dataLength)
187
+ const data = bs58.encode(Buffer.from(dataSlice))
188
+ instructions.push({
189
+ programIdIndex,
190
+ accounts,
191
+ data,
192
+ })
188
193
  }
189
194
 
190
195
  const messageArgs = {
@@ -8,6 +8,7 @@ import { Message } from './message'
8
8
  import { PublicKey } from './publickey'
9
9
  import { PACKET_DATA_SIZE } from './constants'
10
10
  import * as shortvec from './utils/shortvec-encoding'
11
+ import { guardedSplice } from './utils/guarded-array-utils.js'
11
12
 
12
13
  /**
13
14
  * @typedef {string} TransactionSignature
@@ -555,13 +556,12 @@ export class Transaction {
555
556
  */
556
557
  static from(buffer) {
557
558
  // Slice up wire data
558
- let byteArray = [...buffer]
559
+ const byteArray = [...buffer]
559
560
 
560
561
  const signatureCount = shortvec.decodeLength(byteArray)
561
562
  const signatures = []
562
563
  for (let i = 0; i < signatureCount; i++) {
563
- const signature = byteArray.slice(0, SIGNATURE_LENGTH)
564
- byteArray = byteArray.slice(SIGNATURE_LENGTH)
564
+ const signature = guardedSplice(byteArray, 0, SIGNATURE_LENGTH)
565
565
  signatures.push(bs58.encode(Buffer.from(signature)))
566
566
  }
567
567
 
@@ -0,0 +1,30 @@
1
+ // https://github.com/solana-labs/solana-web3.js/blob/master/packages/library-legacy/src/utils/guarded-array-utils.ts
2
+ const END_OF_BUFFER_ERROR_MESSAGE = 'Reached end of buffer unexpectedly'
3
+
4
+ /**
5
+ * Delegates to `Array#shift`, but throws if the array is zero-length.
6
+ */
7
+ export function guardedShift(byteArray) {
8
+ if (byteArray.length === 0) {
9
+ throw new Error(END_OF_BUFFER_ERROR_MESSAGE)
10
+ }
11
+
12
+ return byteArray.shift()
13
+ }
14
+
15
+ /**
16
+ * Delegates to `Array#splice`, but throws if the section being spliced out extends past the end of
17
+ * the array.
18
+ */
19
+ export function guardedSplice(byteArray, ...args) {
20
+ const [start] = args
21
+ if (
22
+ args.length === 2 // Implies that `deleteCount` was supplied
23
+ ? start + (args[1] ?? 0) > byteArray.length
24
+ : start >= byteArray.length
25
+ ) {
26
+ throw new Error(END_OF_BUFFER_ERROR_MESSAGE)
27
+ }
28
+
29
+ return byteArray.splice(...args)
30
+ }