@exodus/solana-lib 1.3.1 → 1.3.3

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.3.1",
3
+ "version": "1.3.3",
4
4
  "description": "Exodus internal Solana low-level library",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -25,5 +25,5 @@
25
25
  "lodash": "^4.17.11",
26
26
  "tweetnacl": "^1.0.3"
27
27
  },
28
- "gitHead": "49f3f78ac41acaf405e2849cccb2f9ecd0060424"
28
+ "gitHead": "e0c7ce8b006cb8cfc78bbd86769b7b5b1890e72b"
29
29
  }
@@ -36,11 +36,15 @@ class Tx {
36
36
  destinationAddressType,
37
37
  isAssociatedTokenAccountActive, // true when recipient balance !== 0
38
38
  fromTokenAddresses, // sender token addresses
39
+ instructions,
40
+ feePayer,
39
41
  } = {}) {
40
- assert(from, 'from is required')
41
- assert(to, 'to is required')
42
- assert(amount, 'amount is required')
43
- assert(typeof amount === 'number', 'amount must be a number')
42
+ if (!instructions) {
43
+ assert(from, 'from is required')
44
+ assert(to, 'to is required')
45
+ assert(amount, 'amount is required')
46
+ assert(typeof amount === 'number', 'amount must be a number')
47
+ }
44
48
  assert(recentBlockhash, 'recentBlockhash is required')
45
49
  if (tokenMintAddress) {
46
50
  assert(
@@ -63,11 +67,15 @@ class Tx {
63
67
  destinationAddressType,
64
68
  isAssociatedTokenAccountActive,
65
69
  fromTokenAddresses,
70
+ instructions,
71
+ feePayer,
66
72
  }
67
73
 
68
74
  if (tokenMintAddress) {
69
75
  // TOKEN transfer tx
70
76
  this.buildTokenTransaction(this.txObj)
77
+ } else if (instructions) {
78
+ this.buildInstructionsTransaction(this.txObj)
71
79
  } else {
72
80
  // SOL tx
73
81
  this.buildSOLtransaction(this.txObj)
@@ -87,6 +95,21 @@ class Tx {
87
95
  })
88
96
  }
89
97
 
98
+ buildInstructionsTransaction({ feePayer, recentBlockhash, instructions }) {
99
+ this.transaction = new Transaction({
100
+ feePayer: new PublicKey(feePayer),
101
+ instructions: instructions.map(i => ({
102
+ programId: new PublicKey(i.programId),
103
+ data: i.data ? Buffer.from(i.data) : Buffer.from([]),
104
+ keys: i.keys.map(k => ({
105
+ ...k,
106
+ pubkey: new PublicKey(k.pubkey)
107
+ }))
108
+ })),
109
+ recentBlockhash,
110
+ })
111
+ }
112
+
90
113
  buildTokenTransaction({
91
114
  from,
92
115
  to,
@@ -325,7 +348,7 @@ class Tx {
325
348
 
326
349
  const info = {
327
350
  txId,
328
- owner: tx.feePayer.toString(), // SOL sender
351
+ owner: tx.getFeePayer().toString(), // SOL sender
329
352
  }
330
353
  const txDetails = stakingInstructions.reduce((info, ix) => {
331
354
  const type = StakeInstruction.decodeInstructionType(ix)
@@ -30,13 +30,16 @@ export function createUnsignedTx({
30
30
  expectedMintAddress,
31
31
  metadataAddress,
32
32
  creators,
33
+ // Wallet Connect
34
+ instructions,
35
+ feePayer,
33
36
  }: ParsedTransaction): UnsignedTransaction {
34
37
  return {
35
38
  txData: {
36
39
  from,
37
40
  to,
38
- amount: amount.toBase().toNumber(),
39
- fee: fee.toBase().toNumber(),
41
+ amount: amount ? amount.toBase().toNumber() : null,
42
+ fee: fee ? fee.toBase().toNumber() : null,
40
43
  recentBlockhash,
41
44
  // Tokens related:
42
45
  tokenMintAddress,
@@ -60,6 +63,9 @@ export function createUnsignedTx({
60
63
  takerAddress,
61
64
  metadataAddress,
62
65
  creators,
66
+ // Wallet Connect
67
+ instructions,
68
+ feePayer,
63
69
  },
64
70
  txMeta: {
65
71
  assetName: asset.name,
package/src/tx/index.js CHANGED
@@ -3,3 +3,4 @@ export * from './parse-unsigned-tx'
3
3
  export * from './create-unsigned-tx'
4
4
  export * from './create-and-sign-tx'
5
5
  export * from './simulate-and-sign-tx'
6
+ export { default as signMessage } from './sign-message'
@@ -0,0 +1,11 @@
1
+ import nacl from 'tweetnacl'
2
+ import bs58 from 'bs58'
3
+
4
+ import { getKeyPairFromPrivateKey } from '../keypair'
5
+
6
+ export default function signMessage({ message, privateKey }) {
7
+ const { secretKey } = getKeyPairFromPrivateKey(privateKey)
8
+ const signature = nacl.sign.detached(bs58.decode(message), secretKey)
9
+ const bs58Signature = bs58.encode(signature)
10
+ return bs58Signature
11
+ }
@@ -33,6 +33,9 @@ export function signUnsignedTx(
33
33
  expectedMintAddress,
34
34
  metadataAddress,
35
35
  creators,
36
+ // Wallet Connect
37
+ instructions,
38
+ feePayer,
36
39
  } = unsignedTx.txData
37
40
 
38
41
  const asset = assets.solana
@@ -112,6 +115,8 @@ export function signUnsignedTx(
112
115
  destinationAddressType,
113
116
  isAssociatedTokenAccountActive,
114
117
  fromTokenAddresses,
118
+ instructions,
119
+ feePayer,
115
120
  })
116
121
  break
117
122
  }
@@ -25,7 +25,7 @@ export function getTransactionSimulationParams(transaction) {
25
25
  }
26
26
  }
27
27
 
28
- const isSolAccount = (account) => account === '1111111111111111'
28
+ const isSolAccount = (account) => account === '11111111111111111111111111111111'
29
29
 
30
30
  export function filterAccountsByOwner(futureAccountsState, accountAddresses, publicKey) {
31
31
  const solAccounts = []
@@ -152,15 +152,22 @@ export class Transaction {
152
152
  }
153
153
  return null
154
154
  }
155
+
155
156
  /**
157
+ * The transaction fee payer
158
+ */
159
+ feePayer: PublicKey;
160
+
161
+ /**
156
162
  * The transaction fee payer (first signer)
157
163
  */
158
- get feePayer(): PublicKey | null {
164
+ getFeePayer(): PublicKey | null {
159
165
  if (this.signatures.length > 0) {
160
166
  return this.signatures[0].publicKey
161
167
  }
162
168
  return null
163
169
  }
170
+
164
171
  /**
165
172
  * The instructions to atomically execute
166
173
  */
@@ -222,8 +229,14 @@ export class Transaction {
222
229
  throw new Error('No instructions provided')
223
230
  }
224
231
 
225
- if (this.feePayer === null) {
226
- throw new Error('Transaction feePayer required')
232
+ let feePayer: PublicKey;
233
+ if (this.feePayer) {
234
+ feePayer = this.feePayer;
235
+ } else if (this.signatures.length > 0 && this.signatures[0].publicKey) {
236
+ // Use implicit fee payer
237
+ feePayer = this.signatures[0].publicKey;
238
+ } else {
239
+ throw new Error('Transaction fee payer required');
227
240
  }
228
241
 
229
242
  const programIds: string[] = []
@@ -268,6 +281,25 @@ export class Transaction {
268
281
  uniqueMetas.push(accountMeta)
269
282
  }
270
283
  })
284
+
285
+ const feePayerIndex = uniqueMetas.findIndex(x => {
286
+ return x.pubkey.equals(feePayer);
287
+ });
288
+
289
+ if (feePayerIndex > -1) {
290
+ const [payerMeta] = uniqueMetas.splice(feePayerIndex, 1);
291
+ payerMeta.isSigner = true;
292
+ payerMeta.isWritable = true;
293
+ uniqueMetas.unshift(payerMeta);
294
+ } else {
295
+ uniqueMetas.unshift({
296
+ pubkey: feePayer,
297
+ isSigner: true,
298
+ isWritable: true
299
+ });
300
+ } // Disallow unknown signers
301
+
302
+
271
303
  // Move payer to the front and disallow unknown signers
272
304
  this.signatures.forEach((signature, signatureIndex) => {
273
305
  const isPayer = signatureIndex === 0