@exodus/solana-lib 1.2.22 → 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 +2 -2
- package/src/encode.js +7 -0
- package/src/keypair.js +9 -0
- package/src/magiceden/__tests__/escrow.test.js +64 -0
- package/src/magiceden/__tests__/fixtures.js +134 -0
- package/src/magiceden/coders.js +41 -0
- package/src/magiceden/escrow-program.js +171 -0
- package/src/transaction.js +84 -2
- package/src/tx/create-unsigned-tx.js +22 -1
- package/src/tx/parse-unsigned-tx.js +19 -0
- package/src/tx/sign-unsigned-tx.js +50 -2
- package/src/vendor/utils/layout.js +18 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/solana-lib",
|
|
3
|
-
"version": "1.2.
|
|
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": "
|
|
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
|
+
}
|
package/src/transaction.js
CHANGED
|
@@ -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
|
|
|
@@ -204,10 +206,90 @@ class Tx {
|
|
|
204
206
|
return transaction
|
|
205
207
|
}
|
|
206
208
|
|
|
207
|
-
static
|
|
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[] = []) {
|
|
208
290
|
if (!privateKey) throw new Error('Please provide a secretKey')
|
|
209
291
|
const { secretKey } = getKeyPairFromPrivateKey(privateKey)
|
|
210
|
-
const signers = [new Account(secretKey)]
|
|
292
|
+
const signers = [new Account(secretKey), ...extraSigners]
|
|
211
293
|
|
|
212
294
|
let transaction = tx
|
|
213
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
|
-
//
|
|
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 {
|
|
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) => {
|