@exodus/solana-lib 1.2.21 → 1.2.23

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.21",
3
+ "version": "1.2.23",
4
4
  "description": "Exodus internal Solana low-level library",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -23,5 +23,5 @@
23
23
  "lodash": "^4.17.11",
24
24
  "tweetnacl": "^1.0.3"
25
25
  },
26
- "gitHead": "dac1d4d133b92c18334de5a37332cfad769e1459"
26
+ "gitHead": "7073b51b6cf558547ca05ae25eaac44cf28a022b"
27
27
  }
package/src/encode.js CHANGED
@@ -1,4 +1,5 @@
1
1
  // @flow
2
+ import assert from 'assert'
2
3
  import { PublicKey, StakeProgram } from './vendor'
3
4
  import { SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID, TOKEN_PROGRAM_ID, SEED } from './constants'
4
5
  import { getPublicKey, getKeyPairFromPrivateKey } from './keypair'
@@ -35,6 +36,12 @@ export function getEncodedSecretKey(privateKey): string {
35
36
  return bs58.encode(secretKey)
36
37
  }
37
38
 
39
+ export function getPrivateKeyFromSecretKey(secretKey: string): string {
40
+ const privateKey = bs58.decode(secretKey).slice(0, 32) // Buffer
41
+ assert(privateKey.length >= 32, 'privateKey has unexpected length')
42
+ return privateKey
43
+ }
44
+
38
45
  // doc: https://spl.solana.com/associated-token-account (HACK: refactored to sync)
39
46
  export function findAssociatedTokenAddress(
40
47
  walletAddress: string,
package/src/keypair.js CHANGED
@@ -12,6 +12,15 @@ export function getKeyPairFromPrivateKey(privateKey: string | Buffer): Object {
12
12
  }
13
13
  }
14
14
 
15
+ export function generateKeyPair() {
16
+ const { publicKey, secretKey } = nacl.sign.keyPair()
17
+
18
+ return {
19
+ secretKey: Buffer.from(secretKey, 'hex'), // secretKey
20
+ publicKey: Buffer.from(publicKey, 'hex'),
21
+ }
22
+ }
23
+
15
24
  export function getPublicKey(privateKey: string | Buffer): Buffer {
16
25
  return getKeyPairFromPrivateKey(privateKey).publicKey
17
26
  }
@@ -0,0 +1,64 @@
1
+ import test from 'tape'
2
+ import { BN } from 'bn.js'
3
+ import { PublicKey } from '../../vendor'
4
+
5
+ import { MagicEdenEscrowProgram } from '../escrow-program'
6
+
7
+ import fixtures from './fixtures'
8
+
9
+ const serializeTx = (tx) => {
10
+ return tx.instructions.map((instruction) => ({
11
+ instructions: instruction.keys.map((k) => ({ ...k, pubkey: k.pubkey.toBase58() })),
12
+ programId: instruction.programId.toBase58(),
13
+ data: instruction.data.toString('hex'),
14
+ }))
15
+ }
16
+
17
+ test('MagicEden: initializeEscrow', (t) => {
18
+ const tx = MagicEdenEscrowProgram.initializeEscrow({
19
+ initializerPubkey: new PublicKey('EpGkR4PcMYHLwZJn7rnxmmLihaZkaAeQLsw4ao3nUUmC'),
20
+ initializerDepositTokenPubkey: new PublicKey('38y2gagfKoVVmLXxqESXWkBLHarzEq6f6cmA1DoAqRnB'),
21
+ escrowPubkey: new PublicKey('AicHKDZR5jLfozYcek5ZHw5mJfxBNFbUwHF2nM4qF8oN'),
22
+ lamports: 500,
23
+ takerAmount: new BN(1e10),
24
+ })
25
+
26
+ t.deepEqual(serializeTx(tx), fixtures.initializeEscrow)
27
+
28
+ t.end()
29
+ })
30
+
31
+ test('MagicEden: cancelEscrow', (t) => {
32
+ const tx = MagicEdenEscrowProgram.cancelEscrow({
33
+ initializerPubkey: new PublicKey('EpGkR4PcMYHLwZJn7rnxmmLihaZkaAeQLsw4ao3nUUmC'),
34
+ initializerDepositTokenPubkey: new PublicKey('38y2gagfKoVVmLXxqESXWkBLHarzEq6f6cmA1DoAqRnB'),
35
+ pdaPubkey: new PublicKey('GUfCR9mK6azb9vcpsxgXyj7XRPAKJd4KMHTTVvtncGgp'),
36
+ escrowPubkey: new PublicKey('AicHKDZR5jLfozYcek5ZHw5mJfxBNFbUwHF2nM4qF8oN'),
37
+ })
38
+
39
+ t.deepEqual(serializeTx(tx), fixtures.cancelEscrow)
40
+
41
+ t.end()
42
+ })
43
+
44
+ test('MagicEden: exchange', (t) => {
45
+ const tx = MagicEdenEscrowProgram.exchange({
46
+ takerPubkey: new PublicKey('FuDxYSDtRAG4P65wxAmUZShBSGtn79o2yJpPF13LQB87'),
47
+ initializerDepositTokenPubkey: new PublicKey('38y2gagfKoVVmLXxqESXWkBLHarzEq6f6cmA1DoAqRnB'),
48
+ initializerPubkey: new PublicKey('EpGkR4PcMYHLwZJn7rnxmmLihaZkaAeQLsw4ao3nUUmC'),
49
+ escrowPubkey: new PublicKey('DvijtTLQGCmmFMPpthitkpP35hGHxdJRxAERjtN13mPg'),
50
+ pdaPubkey: new PublicKey('GUfCR9mK6azb9vcpsxgXyj7XRPAKJd4KMHTTVvtncGgp'),
51
+ metadataPubkey: new PublicKey('4ysTyhoHDAv28dGUD2ASS9zmAHi3QZyXVQW25f6QwWN'),
52
+ creators: [
53
+ {
54
+ address: 'D6ZQMLTJAa14XhzCFBJ2uuPjYDbYfewrVDVSyFZSuBYe',
55
+ verified: 1,
56
+ share: 100,
57
+ },
58
+ ],
59
+ })
60
+
61
+ t.deepEqual(serializeTx(tx), fixtures.exchange)
62
+
63
+ t.end()
64
+ })
@@ -0,0 +1,134 @@
1
+ export default {
2
+ initializeEscrow: [
3
+ {
4
+ instructions: [
5
+ {
6
+ pubkey: 'EpGkR4PcMYHLwZJn7rnxmmLihaZkaAeQLsw4ao3nUUmC',
7
+ isSigner: true,
8
+ isWritable: true,
9
+ },
10
+ {
11
+ pubkey: 'AicHKDZR5jLfozYcek5ZHw5mJfxBNFbUwHF2nM4qF8oN',
12
+ isSigner: true,
13
+ isWritable: true,
14
+ },
15
+ ],
16
+ programId: '11111111111111111111111111111111',
17
+ data:
18
+ '00000000f4010000000000005000000000000000052f21a9fe604e569e956f29223106fa26ce0a21520247a93a07a1489239c8ff',
19
+ },
20
+ {
21
+ instructions: [
22
+ {
23
+ pubkey: 'EpGkR4PcMYHLwZJn7rnxmmLihaZkaAeQLsw4ao3nUUmC',
24
+ isWritable: false,
25
+ isSigner: true,
26
+ },
27
+ {
28
+ pubkey: '38y2gagfKoVVmLXxqESXWkBLHarzEq6f6cmA1DoAqRnB',
29
+ isWritable: true,
30
+ isSigner: false,
31
+ },
32
+ {
33
+ pubkey: 'AicHKDZR5jLfozYcek5ZHw5mJfxBNFbUwHF2nM4qF8oN',
34
+ isWritable: true,
35
+ isSigner: false,
36
+ },
37
+ {
38
+ pubkey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
39
+ isWritable: false,
40
+ isSigner: false,
41
+ },
42
+ ],
43
+ programId: 'MEisE1HzehtrDpAAT8PnLHjpSSkRYakotTuJRPjTpo8',
44
+ data: 'f3a04d990b5c30d100e40b5402000000',
45
+ },
46
+ ],
47
+ cancelEscrow: [
48
+ {
49
+ instructions: [
50
+ {
51
+ pubkey: 'EpGkR4PcMYHLwZJn7rnxmmLihaZkaAeQLsw4ao3nUUmC',
52
+ isWritable: false,
53
+ isSigner: false,
54
+ },
55
+ {
56
+ pubkey: '38y2gagfKoVVmLXxqESXWkBLHarzEq6f6cmA1DoAqRnB',
57
+ isWritable: true,
58
+ isSigner: false,
59
+ },
60
+ {
61
+ pubkey: 'GUfCR9mK6azb9vcpsxgXyj7XRPAKJd4KMHTTVvtncGgp',
62
+ isWritable: false,
63
+ isSigner: false,
64
+ },
65
+ {
66
+ pubkey: 'AicHKDZR5jLfozYcek5ZHw5mJfxBNFbUwHF2nM4qF8oN',
67
+ isWritable: true,
68
+ isSigner: false,
69
+ },
70
+ {
71
+ pubkey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
72
+ isWritable: false,
73
+ isSigner: false,
74
+ },
75
+ ],
76
+ programId: 'MEisE1HzehtrDpAAT8PnLHjpSSkRYakotTuJRPjTpo8',
77
+ data: '9ccb36b326482115',
78
+ },
79
+ ],
80
+ exchange: [
81
+ {
82
+ instructions: [
83
+ {
84
+ pubkey: 'FuDxYSDtRAG4P65wxAmUZShBSGtn79o2yJpPF13LQB87',
85
+ isWritable: false,
86
+ isSigner: true,
87
+ },
88
+ {
89
+ pubkey: '38y2gagfKoVVmLXxqESXWkBLHarzEq6f6cmA1DoAqRnB',
90
+ isWritable: true,
91
+ isSigner: false,
92
+ },
93
+ {
94
+ pubkey: 'EpGkR4PcMYHLwZJn7rnxmmLihaZkaAeQLsw4ao3nUUmC',
95
+ isWritable: true,
96
+ isSigner: false,
97
+ },
98
+ {
99
+ pubkey: 'DvijtTLQGCmmFMPpthitkpP35hGHxdJRxAERjtN13mPg',
100
+ isWritable: true,
101
+ isSigner: false,
102
+ },
103
+ {
104
+ pubkey: 'GUfCR9mK6azb9vcpsxgXyj7XRPAKJd4KMHTTVvtncGgp',
105
+ isWritable: false,
106
+ isSigner: false,
107
+ },
108
+ { pubkey: '11111111111111111111111111111111', isWritable: false, isSigner: false },
109
+ {
110
+ pubkey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
111
+ isWritable: false,
112
+ isSigner: false,
113
+ },
114
+ {
115
+ pubkey: '2NZukH2TXpcuZP4htiuT8CFxcaQSWzkkR6kepSWnZ24Q',
116
+ isWritable: true,
117
+ isSigner: false,
118
+ },
119
+ {
120
+ pubkey: '4ysTyhoHDAv28dGUD2ASS9zmAHi3QZyXVQW25f6QwWN',
121
+ isWritable: false,
122
+ isSigner: false,
123
+ },
124
+ {
125
+ pubkey: 'D6ZQMLTJAa14XhzCFBJ2uuPjYDbYfewrVDVSyFZSuBYe',
126
+ isWritable: true,
127
+ isSigner: false,
128
+ },
129
+ ],
130
+ programId: 'MEisE1HzehtrDpAAT8PnLHjpSSkRYakotTuJRPjTpo8',
131
+ data: '2f031b61d7ecdb90',
132
+ },
133
+ ],
134
+ }
@@ -0,0 +1,41 @@
1
+ import * as BufferLayout from '@exodus/buffer-layout'
2
+
3
+ import { snakeCase } from 'lodash'
4
+ import createHash from 'create-hash'
5
+
6
+ import { bnAmountU64 } from '../vendor/utils/layout'
7
+
8
+ const idl = {
9
+ initializeEscrow: {
10
+ name: 'initializeEscrow',
11
+ layout: BufferLayout.struct([bnAmountU64('takerAmount')]),
12
+ },
13
+ cancelEscrow: {
14
+ name: 'cancelEscrow',
15
+ layout: BufferLayout.struct([]),
16
+ },
17
+ exchange: {
18
+ name: 'exchange',
19
+ layout: BufferLayout.struct([]),
20
+ },
21
+ }
22
+
23
+ export function sighash(nameSpace, ixName) {
24
+ let name = snakeCase(ixName)
25
+ let preimage = `${nameSpace}:${name}`
26
+
27
+ return Buffer.from(
28
+ createHash('sha256')
29
+ .update(preimage)
30
+ .digest()
31
+ ).slice(0, 8)
32
+ }
33
+
34
+ export function encodeData(name, args = {}) {
35
+ const idlInstruction = idl[name]
36
+
37
+ const buffer = Buffer.alloc(idlInstruction.layout.span)
38
+ const len = idlInstruction.layout.encode(args, buffer)
39
+
40
+ return Buffer.concat([sighash('global', idlInstruction.name), buffer.slice(0, len)])
41
+ }
@@ -0,0 +1,171 @@
1
+ import { PublicKey, Transaction, SystemProgram } from '../vendor'
2
+ import { SYSTEM_PROGRAM_ID, TOKEN_PROGRAM_ID } from '../constants'
3
+ import { encodeData } from './coders'
4
+
5
+ const PLATFORM_FEES_PROGRAM_ID = new PublicKey('2NZukH2TXpcuZP4htiuT8CFxcaQSWzkkR6kepSWnZ24Q')
6
+
7
+ export class MagicEdenEscrowProgram {
8
+ static get programId() {
9
+ return new PublicKey('MEisE1HzehtrDpAAT8PnLHjpSSkRYakotTuJRPjTpo8')
10
+ }
11
+
12
+ static get space() {
13
+ return 80
14
+ }
15
+
16
+ static initializeEscrow(params) {
17
+ const {
18
+ initializerPubkey,
19
+ initializerDepositTokenPubkey,
20
+ escrowPubkey,
21
+ lamports,
22
+ takerAmount,
23
+ } = params
24
+
25
+ const transaction = new Transaction()
26
+
27
+ transaction.add(
28
+ SystemProgram.createAccount({
29
+ fromPubkey: initializerPubkey,
30
+ newAccountPubkey: escrowPubkey,
31
+ lamports: lamports,
32
+ space: this.space,
33
+ programId: this.programId,
34
+ })
35
+ )
36
+
37
+ return transaction.add({
38
+ keys: [
39
+ {
40
+ pubkey: initializerPubkey,
41
+ isSigner: true,
42
+ isWritable: false,
43
+ },
44
+ {
45
+ pubkey: initializerDepositTokenPubkey,
46
+ isSigner: false,
47
+ isWritable: true,
48
+ },
49
+ {
50
+ pubkey: escrowPubkey,
51
+ isSigner: false,
52
+ isWritable: true,
53
+ },
54
+ {
55
+ pubkey: TOKEN_PROGRAM_ID,
56
+ isSigner: false,
57
+ isWritable: false,
58
+ },
59
+ ],
60
+ programId: this.programId,
61
+ data: encodeData('initializeEscrow', { takerAmount }),
62
+ })
63
+ }
64
+
65
+ static cancelEscrow(params) {
66
+ const { initializerPubkey, initializerDepositTokenPubkey, pdaPubkey, escrowPubkey } = params
67
+
68
+ return new Transaction().add({
69
+ keys: [
70
+ {
71
+ pubkey: initializerPubkey,
72
+ isSigner: false,
73
+ isWritable: false,
74
+ },
75
+ {
76
+ pubkey: initializerDepositTokenPubkey,
77
+ isSigner: false,
78
+ isWritable: true,
79
+ },
80
+ {
81
+ pubkey: pdaPubkey,
82
+ isSigner: false,
83
+ isWritable: false,
84
+ },
85
+ {
86
+ pubkey: escrowPubkey,
87
+ isSigner: false,
88
+ isWritable: true,
89
+ },
90
+ {
91
+ pubkey: TOKEN_PROGRAM_ID,
92
+ isSigner: false,
93
+ isWritable: false,
94
+ },
95
+ ],
96
+ programId: this.programId,
97
+ data: encodeData('cancelEscrow'),
98
+ })
99
+ }
100
+
101
+ static exchange(params) {
102
+ const {
103
+ takerPubkey,
104
+ initializerDepositTokenPubkey,
105
+ initializerPubkey,
106
+ escrowPubkey,
107
+ pdaPubkey,
108
+ metadataPubkey,
109
+ creators,
110
+ } = params
111
+
112
+ const remainingAccounts = creators.map((c) => ({
113
+ pubkey: new PublicKey(c.address),
114
+ isWritable: true,
115
+ isSigner: false,
116
+ }))
117
+
118
+ return new Transaction().add({
119
+ keys: [
120
+ {
121
+ pubkey: takerPubkey,
122
+ isSigner: true,
123
+ isWritable: false,
124
+ },
125
+ {
126
+ pubkey: initializerDepositTokenPubkey,
127
+ isSigner: false,
128
+ isWritable: true,
129
+ },
130
+ {
131
+ pubkey: initializerPubkey,
132
+ isSigner: false,
133
+ isWritable: true,
134
+ },
135
+ {
136
+ pubkey: escrowPubkey,
137
+ isSigner: false,
138
+ isWritable: true,
139
+ },
140
+ {
141
+ pubkey: pdaPubkey,
142
+ isSigner: false,
143
+ isWritable: false,
144
+ },
145
+ {
146
+ pubkey: SYSTEM_PROGRAM_ID,
147
+ isSigner: false,
148
+ isWritable: false,
149
+ },
150
+ {
151
+ pubkey: TOKEN_PROGRAM_ID,
152
+ isSigner: false,
153
+ isWritable: false,
154
+ },
155
+ {
156
+ pubkey: PLATFORM_FEES_PROGRAM_ID,
157
+ isSigner: false,
158
+ isWritable: true,
159
+ },
160
+ {
161
+ pubkey: metadataPubkey,
162
+ isSigner: false,
163
+ isWritable: false,
164
+ },
165
+ ...remainingAccounts,
166
+ ],
167
+ programId: this.programId,
168
+ data: encodeData('exchange'),
169
+ })
170
+ }
171
+ }
@@ -2,6 +2,7 @@
2
2
  import assert from 'assert'
3
3
  import bs58 from 'bs58'
4
4
  import { get } from 'lodash'
5
+ import assets from '@exodus/assets'
5
6
 
6
7
  import { getKeyPairFromPrivateKey } from './keypair'
7
8
  import { findAssociatedTokenAddress, createStakeAddress } from './encode'
@@ -19,6 +20,7 @@ import {
19
20
  Authorized,
20
21
  Lockup,
21
22
  } from './vendor'
23
+ import { MagicEdenEscrowProgram } from './magiceden/escrow-program'
22
24
  import { SEED, STAKE_PROGRAM_ID } from './constants'
23
25
  import TOKENS from './tokens'
24
26
 
@@ -56,7 +58,8 @@ class Tx {
56
58
 
57
59
  if (tokenName && !tokenMintAddress) {
58
60
  const token = TOKENS.find(({ name }) => name === tokenName)
59
- tokenMintAddress = token && token.mintAddress
61
+ assert(token, `token with tokenName ${tokenName} not found in tokens list`)
62
+ tokenMintAddress = token.mintAddress
60
63
  }
61
64
 
62
65
  this.txObj = {
@@ -107,7 +110,7 @@ class Tx {
107
110
  })
108
111
  // const isUnknown = destinationAddressType === null
109
112
  // if (isUnknown) throw new Error('Destination SOL balance cannot be zero (address not active)') // cannot initialize without knowing the owner
110
- const isSOLaddress = destinationAddressType === 'solana'
113
+ const isSOLaddress = ['solana', null].includes(destinationAddressType)
111
114
  // crete account instruction
112
115
  if (isSOLaddress && !isAssociatedTokenAccountActive)
113
116
  this.transaction.add(createAssociatedTokenAccount(from, tokenMintAddress, to))
@@ -203,10 +206,90 @@ class Tx {
203
206
  return transaction
204
207
  }
205
208
 
206
- static sign(tx, privateKey: Buffer | string) {
209
+ static magicEdenInitializeEscrow({
210
+ initializerAddress,
211
+ initializerDepositTokenAddress,
212
+ lamports,
213
+ takerAmount,
214
+ escrowAccount,
215
+ recentBlockhash,
216
+ }) {
217
+ const initializerPubkey = new PublicKey(initializerAddress)
218
+ const initializerDepositTokenPubkey = new PublicKey(initializerDepositTokenAddress)
219
+
220
+ const transaction = MagicEdenEscrowProgram.initializeEscrow({
221
+ initializerPubkey,
222
+ initializerDepositTokenPubkey,
223
+ escrowPubkey: escrowAccount.publicKey,
224
+ lamports,
225
+ takerAmount: assets.solana.currency.baseUnit(takerAmount)._number,
226
+ })
227
+
228
+ transaction.recentBlockhash = recentBlockhash
229
+
230
+ return transaction
231
+ }
232
+
233
+ static magicEdenCancelEscrow({
234
+ initializerAddress,
235
+ initializerDepositTokenAddress,
236
+ escrowAddress,
237
+ pdaAddress,
238
+ recentBlockhash,
239
+ }) {
240
+ const initializerPubkey = new PublicKey(initializerAddress)
241
+ const initializerDepositTokenPubkey = new PublicKey(initializerDepositTokenAddress)
242
+ const escrowPubkey = new PublicKey(escrowAddress)
243
+ const pdaPubkey = new PublicKey(pdaAddress)
244
+
245
+ const transaction = MagicEdenEscrowProgram.cancelEscrow({
246
+ initializerPubkey,
247
+ initializerDepositTokenPubkey,
248
+ escrowPubkey,
249
+ pdaPubkey,
250
+ })
251
+
252
+ transaction.recentBlockhash = recentBlockhash
253
+
254
+ return transaction
255
+ }
256
+
257
+ static magicEdenExchange({
258
+ takerAddress,
259
+ initializerAddress,
260
+ initializerDepositTokenAddress,
261
+ escrowAddress,
262
+ pdaAddress,
263
+ metadataAddress,
264
+ creators,
265
+ recentBlockhash,
266
+ }) {
267
+ const takerPubkey = new PublicKey(takerAddress)
268
+ const initializerPubkey = new PublicKey(initializerAddress)
269
+ const initializerDepositTokenPubkey = new PublicKey(initializerDepositTokenAddress)
270
+ const escrowPubkey = new PublicKey(escrowAddress)
271
+ const pdaPubkey = new PublicKey(pdaAddress)
272
+ const metadataPubkey = new PublicKey(metadataAddress)
273
+
274
+ const transaction = MagicEdenEscrowProgram.exchange({
275
+ takerPubkey,
276
+ initializerPubkey,
277
+ initializerDepositTokenPubkey,
278
+ escrowPubkey,
279
+ pdaPubkey,
280
+ metadataPubkey,
281
+ creators,
282
+ })
283
+
284
+ transaction.recentBlockhash = recentBlockhash
285
+
286
+ return transaction
287
+ }
288
+
289
+ static sign(tx, privateKey: Buffer | string, extraSigners: Account[] = []) {
207
290
  if (!privateKey) throw new Error('Please provide a secretKey')
208
291
  const { secretKey } = getKeyPairFromPrivateKey(privateKey)
209
- const signers = [new Account(secretKey)]
292
+ const signers = [new Account(secretKey), ...extraSigners]
210
293
 
211
294
  let transaction = tx
212
295
  if (tx instanceof Tx) transaction = tx.transaction
@@ -13,11 +13,22 @@ export function createUnsignedTx({
13
13
  destinationAddressType,
14
14
  isAssociatedTokenAccountActive, // true when recipient balance !== 0
15
15
  fromTokenAddresses, // sender token addresses
16
- // Staking related:
16
+ // Program interactions:
17
17
  method,
18
+ // Staking related:
18
19
  stakeAddresses,
19
20
  seed,
20
21
  pool,
22
+ // MagicEden escrow/related:
23
+ initializerAddress,
24
+ initializerDepositTokenAddress,
25
+ lamports,
26
+ takerAmount,
27
+ escrowAddress,
28
+ pdaAddress,
29
+ takerAddress,
30
+ metadataAddress,
31
+ creators,
21
32
  }: ParsedTransaction): UnsignedTransaction {
22
33
  return {
23
34
  txData: {
@@ -37,6 +48,16 @@ export function createUnsignedTx({
37
48
  stakeAddresses,
38
49
  seed,
39
50
  pool,
51
+ // MagicEden escrow/related:
52
+ initializerAddress,
53
+ initializerDepositTokenAddress,
54
+ lamports,
55
+ takerAmount: takerAmount ? takerAmount.toBaseString() : null,
56
+ escrowAddress,
57
+ pdaAddress,
58
+ takerAddress,
59
+ metadataAddress,
60
+ creators,
40
61
  },
41
62
  txMeta: {
42
63
  assetName: asset.name,
@@ -16,6 +16,15 @@ export function parseUnsignedTx(unsignedTx: UnsignedTransaction): ParsedTransact
16
16
  stakeAddresses,
17
17
  seed,
18
18
  pool,
19
+ initializerAddress,
20
+ initializerDepositTokenAddress,
21
+ lamports,
22
+ takerAmount,
23
+ escrowAddress,
24
+ pdaAddress,
25
+ takerAddress,
26
+ metadataAddress,
27
+ creators,
19
28
  ...txData
20
29
  } = unsignedTx.txData
21
30
 
@@ -39,5 +48,15 @@ export function parseUnsignedTx(unsignedTx: UnsignedTransaction): ParsedTransact
39
48
  stakeAddresses,
40
49
  seed,
41
50
  pool,
51
+ // MagicEden escrow/related:
52
+ initializerAddress,
53
+ initializerDepositTokenAddress,
54
+ lamports,
55
+ takerAmount: asset.currency.baseUnit(txData.takerAmount),
56
+ escrowAddress,
57
+ pdaAddress,
58
+ takerAddress,
59
+ metadataAddress,
60
+ creators,
42
61
  }
43
62
  }
@@ -1,6 +1,7 @@
1
1
  import assets from '@exodus/assets'
2
2
  import type { UnsignedTransaction, SignedTransaction } from '@exodus/models/lib/types'
3
- import { Transaction } from '../'
3
+ import { Account } from '../vendor'
4
+ import { Transaction, generateKeyPair } from '../'
4
5
 
5
6
  export function signUnsignedTx(
6
7
  unsignedTx: UnsignedTransaction,
@@ -22,6 +23,16 @@ export function signUnsignedTx(
22
23
  method,
23
24
  seed,
24
25
  pool,
26
+ // MagicEden escrow/related:
27
+ initializerAddress,
28
+ initializerDepositTokenAddress,
29
+ lamports,
30
+ takerAmount,
31
+ escrowAddress,
32
+ pdaAddress,
33
+ takerAddress,
34
+ metadataAddress,
35
+ creators,
25
36
  } = unsignedTx.txData
26
37
 
27
38
  const asset = assets.solana
@@ -30,6 +41,7 @@ export function signUnsignedTx(
30
41
  const amount = unitAmount ? asset.currency.baseUnit(unitAmount).toNumber() : unitAmount
31
42
 
32
43
  let tx
44
+ const extraSigners = []
33
45
  switch (method) {
34
46
  case 'delegate':
35
47
  tx = Transaction.createStakeAccountTransaction({
@@ -55,6 +67,42 @@ export function signUnsignedTx(
55
67
  recentBlockhash,
56
68
  })
57
69
  break
70
+ case 'initializeEscrow': {
71
+ const escrowAccount = new Account(generateKeyPair().secretKey)
72
+
73
+ tx = Transaction.magicEdenInitializeEscrow({
74
+ initializerAddress,
75
+ initializerDepositTokenAddress,
76
+ lamports,
77
+ takerAmount,
78
+ escrowAccount,
79
+ recentBlockhash,
80
+ })
81
+
82
+ extraSigners.push(escrowAccount)
83
+ break
84
+ }
85
+ case 'cancelEscrow':
86
+ tx = Transaction.magicEdenCancelEscrow({
87
+ initializerAddress,
88
+ initializerDepositTokenAddress,
89
+ escrowAddress,
90
+ pdaAddress,
91
+ recentBlockhash,
92
+ })
93
+ break
94
+ case 'exchange':
95
+ tx = Transaction.magicEdenExchange({
96
+ takerAddress,
97
+ initializerAddress,
98
+ initializerDepositTokenAddress,
99
+ escrowAddress,
100
+ pdaAddress,
101
+ metadataAddress,
102
+ creators,
103
+ recentBlockhash,
104
+ })
105
+ break
58
106
  default:
59
107
  // SOL and Token tx
60
108
  tx = new Transaction({
@@ -72,7 +120,7 @@ export function signUnsignedTx(
72
120
  }
73
121
 
74
122
  // sign plain tx
75
- Transaction.sign(tx, privateKey)
123
+ Transaction.sign(tx, privateKey, extraSigners)
76
124
  const rawTx = Transaction.serialize(tx)
77
125
  const txId = Transaction.getTxId(tx)
78
126
 
@@ -1,5 +1,5 @@
1
1
  // @flow
2
-
2
+ import BN from 'bn.js'
3
3
  import * as BufferLayout from '@exodus/buffer-layout'
4
4
 
5
5
  /**
@@ -67,6 +67,23 @@ export const lockup = (property: string = 'lockup') => {
67
67
  )
68
68
  }
69
69
 
70
+ export const bnAmountU64 = (property: string) => {
71
+ const rsl = BufferLayout.blob(8, property)
72
+
73
+ const _decode = rsl.decode.bind(rsl)
74
+ const _encode = rsl.encode.bind(rsl)
75
+
76
+ rsl.decode = (b, offset = 0) => {
77
+ return new BN(_decode(b, offset), 10, 'le')
78
+ }
79
+
80
+ rsl.encode = (src, b, offset = 0) => {
81
+ return _encode(src.toArrayLike(Buffer, 'le', 8), b, offset)
82
+ }
83
+
84
+ return rsl
85
+ }
86
+
70
87
  export function getAlloc(type: Object, fields: Object): number {
71
88
  let alloc = 0
72
89
  type.layout.fields.forEach((item) => {