@exodus/solana-lib 1.3.14 → 1.4.0
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 +3 -3
- package/src/constants.js +2 -0
- package/src/helpers/tokenTransfer.js +15 -1
- package/src/index.js +1 -0
- package/src/transaction.js +61 -5
- package/src/tx/sign-unsigned-tx.js +155 -96
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/solana-lib",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Exodus internal Solana low-level library",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"files": [
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"access": "restricted"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@exodus/asset-lib": "^3.6.
|
|
16
|
+
"@exodus/asset-lib": "^3.6.2",
|
|
17
17
|
"@exodus/assets": "^8.0.68",
|
|
18
18
|
"@exodus/assets-base": "^8.0.139",
|
|
19
19
|
"@exodus/buffer-layout": "^1.2.0-exodus1",
|
|
@@ -29,5 +29,5 @@
|
|
|
29
29
|
"lodash": "^4.17.11",
|
|
30
30
|
"tweetnacl": "^1.0.3"
|
|
31
31
|
},
|
|
32
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "6ffded97383f994c21ccaebb2703c32d48aa70c5"
|
|
33
33
|
}
|
package/src/constants.js
CHANGED
|
@@ -9,6 +9,8 @@ export const STAKE_PROGRAM_ID = StakeProgram.programId
|
|
|
9
9
|
|
|
10
10
|
export const TOKEN_PROGRAM_ID = new PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA')
|
|
11
11
|
|
|
12
|
+
export const MEMO_PROGRAM_ID = new PublicKey('MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr')
|
|
13
|
+
|
|
12
14
|
export const MAGIC_EDEN_ESCROW_PROGRAM_ID = new PublicKey(
|
|
13
15
|
'MEisE1HzehtrDpAAT8PnLHjpSSkRYakotTuJRPjTpo8'
|
|
14
16
|
)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Token } from '
|
|
1
|
+
import { Token } from '@exodus/solana-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'
|
|
@@ -70,3 +70,17 @@ export const createTokenTransferInstruction = (owner, fromTokenAddress, to, amou
|
|
|
70
70
|
|
|
71
71
|
return transferIx
|
|
72
72
|
}
|
|
73
|
+
|
|
74
|
+
export const createCloseAccountInstruction = ({
|
|
75
|
+
programId = TOKEN_PROGRAM_ID,
|
|
76
|
+
tokenPublicKey,
|
|
77
|
+
walletPublicKey,
|
|
78
|
+
}) => {
|
|
79
|
+
return Token.createCloseAccountInstruction(
|
|
80
|
+
programId,
|
|
81
|
+
tokenPublicKey,
|
|
82
|
+
walletPublicKey,
|
|
83
|
+
walletPublicKey,
|
|
84
|
+
[]
|
|
85
|
+
)
|
|
86
|
+
}
|
package/src/index.js
CHANGED
package/src/transaction.js
CHANGED
|
@@ -9,6 +9,7 @@ import { findAssociatedTokenAddress, createStakeAddress } from './encode'
|
|
|
9
9
|
import {
|
|
10
10
|
createAssociatedTokenAccount,
|
|
11
11
|
createTokenTransferInstruction,
|
|
12
|
+
createCloseAccountInstruction,
|
|
12
13
|
} from './helpers/tokenTransfer'
|
|
13
14
|
import {
|
|
14
15
|
PublicKey,
|
|
@@ -19,9 +20,10 @@ import {
|
|
|
19
20
|
StakeInstruction,
|
|
20
21
|
Authorized,
|
|
21
22
|
Lockup,
|
|
23
|
+
TransactionInstruction,
|
|
22
24
|
} from './vendor'
|
|
23
25
|
import { MagicEdenEscrowProgram } from './magiceden/escrow-program'
|
|
24
|
-
import { SEED, STAKE_PROGRAM_ID } from './constants'
|
|
26
|
+
import { MEMO_PROGRAM_ID, SEED, STAKE_PROGRAM_ID } from './constants'
|
|
25
27
|
|
|
26
28
|
class Tx {
|
|
27
29
|
constructor({
|
|
@@ -38,6 +40,8 @@ class Tx {
|
|
|
38
40
|
fromTokenAddresses, // sender token addresses
|
|
39
41
|
instructions,
|
|
40
42
|
feePayer,
|
|
43
|
+
memo,
|
|
44
|
+
reference,
|
|
41
45
|
} = {}) {
|
|
42
46
|
if (!instructions) {
|
|
43
47
|
assert(from, 'from is required')
|
|
@@ -69,6 +73,7 @@ class Tx {
|
|
|
69
73
|
fromTokenAddresses,
|
|
70
74
|
instructions,
|
|
71
75
|
feePayer,
|
|
76
|
+
reference,
|
|
72
77
|
}
|
|
73
78
|
|
|
74
79
|
if (tokenMintAddress) {
|
|
@@ -80,18 +85,41 @@ class Tx {
|
|
|
80
85
|
// SOL tx
|
|
81
86
|
this.buildSOLtransaction(this.txObj)
|
|
82
87
|
}
|
|
88
|
+
|
|
89
|
+
// If a memo is provided, add it to the transaction before adding the transfer instruction
|
|
90
|
+
if (memo) {
|
|
91
|
+
this.transaction.add(
|
|
92
|
+
new TransactionInstruction({
|
|
93
|
+
programId: MEMO_PROGRAM_ID,
|
|
94
|
+
keys: [],
|
|
95
|
+
data: Buffer.from(memo, 'utf8'),
|
|
96
|
+
})
|
|
97
|
+
)
|
|
98
|
+
}
|
|
83
99
|
}
|
|
84
100
|
|
|
85
|
-
buildSOLtransaction({ from, to, amount, recentBlockhash }) {
|
|
101
|
+
buildSOLtransaction({ from, to, amount, recentBlockhash, feePayer, reference }) {
|
|
86
102
|
const txInstruction = SystemProgram.transfer({
|
|
87
103
|
fromPubkey: new PublicKey(from),
|
|
88
104
|
toPubkey: new PublicKey(to),
|
|
89
105
|
lamports: amount,
|
|
90
106
|
})
|
|
91
107
|
|
|
108
|
+
// If reference accounts are provided, add them to the transfer instruction
|
|
109
|
+
if (reference) {
|
|
110
|
+
if (!Array.isArray(reference)) {
|
|
111
|
+
reference = [reference]
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
for (const pubkey of reference) {
|
|
115
|
+
txInstruction.keys.push({ pubkey, isWritable: false, isSigner: false })
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
92
119
|
this.transaction = new Transaction({
|
|
93
120
|
instructions: [txInstruction],
|
|
94
121
|
recentBlockhash,
|
|
122
|
+
feePayer: feePayer ? new PublicKey(feePayer) : undefined,
|
|
95
123
|
})
|
|
96
124
|
}
|
|
97
125
|
|
|
@@ -119,9 +147,12 @@ class Tx {
|
|
|
119
147
|
destinationAddressType,
|
|
120
148
|
isAssociatedTokenAccountActive,
|
|
121
149
|
fromTokenAddresses,
|
|
150
|
+
feePayer,
|
|
151
|
+
reference,
|
|
122
152
|
}) {
|
|
123
153
|
this.transaction = new Transaction({
|
|
124
154
|
recentBlockhash,
|
|
155
|
+
feePayer: feePayer ? new PublicKey(feePayer) : undefined,
|
|
125
156
|
})
|
|
126
157
|
// const isUnknown = destinationAddressType === null
|
|
127
158
|
// if (isUnknown) throw new Error('Destination SOL balance cannot be zero (address not active)') // cannot initialize without knowing the owner
|
|
@@ -147,10 +178,26 @@ class Tx {
|
|
|
147
178
|
}
|
|
148
179
|
|
|
149
180
|
const dest = isSOLaddress ? findAssociatedTokenAddress(to, tokenMintAddress) : to
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
181
|
+
const tokenTransferInstruction = createTokenTransferInstruction(
|
|
182
|
+
from,
|
|
183
|
+
tokenAccountAddress,
|
|
184
|
+
dest,
|
|
185
|
+
amountToSend
|
|
153
186
|
)
|
|
187
|
+
|
|
188
|
+
// If reference accounts are provided, add them to the transfer instruction
|
|
189
|
+
if (reference) {
|
|
190
|
+
if (!Array.isArray(reference)) {
|
|
191
|
+
reference = [reference]
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
for (const pubkey of reference) {
|
|
195
|
+
tokenTransferInstruction.keys.push({ pubkey, isWritable: false, isSigner: false })
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// add transfer token instruction
|
|
200
|
+
this.transaction.add(tokenTransferInstruction)
|
|
154
201
|
}
|
|
155
202
|
|
|
156
203
|
assert(amountLeft === 0, `Not enough balance to send ${amount} ${tokenMintAddress}`)
|
|
@@ -397,6 +444,15 @@ class Tx {
|
|
|
397
444
|
}
|
|
398
445
|
return bs58.encode(transaction.signature)
|
|
399
446
|
}
|
|
447
|
+
|
|
448
|
+
static createCloseAccount({ programId, tokenPublicKey, walletPublicKey, recentBlockhash }) {
|
|
449
|
+
const tx = new Transaction()
|
|
450
|
+
tx.add(createCloseAccountInstruction({ programId, tokenPublicKey, walletPublicKey }))
|
|
451
|
+
tx.feePayer = walletPublicKey
|
|
452
|
+
tx.recentBlockhash = recentBlockhash
|
|
453
|
+
|
|
454
|
+
return tx
|
|
455
|
+
}
|
|
400
456
|
}
|
|
401
457
|
|
|
402
458
|
export default Tx
|
|
@@ -1,130 +1,189 @@
|
|
|
1
|
+
import { merge } from 'lodash'
|
|
1
2
|
import assets from '@exodus/assets'
|
|
2
3
|
import type { UnsignedTransaction, SignedTransaction } from '@exodus/models/lib/types'
|
|
4
|
+
|
|
3
5
|
import { Transaction } from '../'
|
|
4
6
|
|
|
5
7
|
export function signUnsignedTx(
|
|
6
8
|
unsignedTx: UnsignedTransaction,
|
|
7
9
|
privateKey: Buffer
|
|
8
10
|
): SignedTransaction {
|
|
9
|
-
const {
|
|
10
|
-
from,
|
|
11
|
-
to,
|
|
12
|
-
amount: unitAmount,
|
|
13
|
-
recentBlockhash,
|
|
14
|
-
// tokens related
|
|
15
|
-
tokenMintAddress,
|
|
16
|
-
destinationAddressType,
|
|
17
|
-
isAssociatedTokenAccountActive,
|
|
18
|
-
fromTokenAddresses,
|
|
19
|
-
// staking related
|
|
20
|
-
stakeAddresses,
|
|
21
|
-
method,
|
|
22
|
-
seed,
|
|
23
|
-
pool,
|
|
24
|
-
// MagicEden escrow/related:
|
|
25
|
-
initializerAddress,
|
|
26
|
-
initializerDepositTokenAddress,
|
|
27
|
-
takerAmount,
|
|
28
|
-
escrowAddress,
|
|
29
|
-
escrowBump,
|
|
30
|
-
pdaAddress,
|
|
31
|
-
takerAddress,
|
|
32
|
-
expectedTakerAmount,
|
|
33
|
-
expectedMintAddress,
|
|
34
|
-
metadataAddress,
|
|
35
|
-
creators,
|
|
36
|
-
// Wallet Connect
|
|
37
|
-
instructions,
|
|
38
|
-
feePayer,
|
|
39
|
-
} = unsignedTx.txData
|
|
11
|
+
const { amount: unitAmount, from, method, transaction } = unsignedTx.txData
|
|
40
12
|
|
|
41
|
-
|
|
13
|
+
if (transaction) {
|
|
14
|
+
return _signTx({ tx: transaction, privateKey })
|
|
15
|
+
}
|
|
42
16
|
|
|
17
|
+
const asset = assets.solana
|
|
43
18
|
const address = from
|
|
44
19
|
const amount = unitAmount ? asset.currency.baseUnit(unitAmount).toNumber() : unitAmount
|
|
45
20
|
|
|
21
|
+
const args = merge(unsignedTx.txData, {
|
|
22
|
+
asset,
|
|
23
|
+
address,
|
|
24
|
+
amount,
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
const tx = createTx({ txData: args, method })
|
|
28
|
+
return _signTx({ tx, privateKey })
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Signs plain tx.
|
|
32
|
+
const _signTx = ({ tx, privateKey }) => {
|
|
33
|
+
Transaction.sign(tx, privateKey)
|
|
34
|
+
const rawTx = Transaction.serialize(tx)
|
|
35
|
+
const txId = Transaction.getTxId(tx)
|
|
36
|
+
|
|
37
|
+
return { txId, rawTx }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const createTx = ({ txData, method }) => {
|
|
46
41
|
let tx
|
|
47
42
|
switch (method) {
|
|
48
43
|
case 'delegate':
|
|
49
|
-
tx =
|
|
50
|
-
address,
|
|
51
|
-
amount,
|
|
52
|
-
recentBlockhash,
|
|
53
|
-
seed,
|
|
54
|
-
pool,
|
|
55
|
-
})
|
|
44
|
+
tx = createDelegateTransaction(txData)
|
|
56
45
|
break
|
|
57
46
|
case 'undelegate':
|
|
58
|
-
tx =
|
|
59
|
-
address,
|
|
60
|
-
stakeAddresses,
|
|
61
|
-
recentBlockhash,
|
|
62
|
-
})
|
|
47
|
+
tx = createUndelegateTransaction(txData)
|
|
63
48
|
break
|
|
64
49
|
case 'withdraw':
|
|
65
|
-
tx =
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
recentBlockhash,
|
|
70
|
-
})
|
|
50
|
+
tx = createWithdrawTransaction(txData)
|
|
51
|
+
break
|
|
52
|
+
case 'closeAccount':
|
|
53
|
+
tx = createCloseAccountTransaction(txData)
|
|
71
54
|
break
|
|
72
55
|
case 'initializeEscrow': {
|
|
73
|
-
tx =
|
|
74
|
-
initializerAddress,
|
|
75
|
-
initializerDepositTokenAddress,
|
|
76
|
-
escrowBump,
|
|
77
|
-
escrowAddress,
|
|
78
|
-
takerAmount,
|
|
79
|
-
recentBlockhash,
|
|
80
|
-
})
|
|
81
|
-
|
|
56
|
+
tx = createMagicEdenInitializeEscrowTransaction(txData)
|
|
82
57
|
break
|
|
83
58
|
}
|
|
84
59
|
case 'cancelEscrow':
|
|
85
|
-
tx =
|
|
86
|
-
initializerAddress,
|
|
87
|
-
initializerDepositTokenAddress,
|
|
88
|
-
escrowAddress,
|
|
89
|
-
pdaAddress,
|
|
90
|
-
recentBlockhash,
|
|
91
|
-
})
|
|
60
|
+
tx = createMagicEdenCancelEscrowTransaction(txData)
|
|
92
61
|
break
|
|
93
62
|
case 'exchange':
|
|
94
|
-
tx =
|
|
95
|
-
expectedTakerAmount,
|
|
96
|
-
expectedMintAddress,
|
|
97
|
-
takerAddress,
|
|
98
|
-
initializerAddress,
|
|
99
|
-
initializerDepositTokenAddress,
|
|
100
|
-
escrowAddress,
|
|
101
|
-
pdaAddress,
|
|
102
|
-
metadataAddress,
|
|
103
|
-
creators,
|
|
104
|
-
recentBlockhash,
|
|
105
|
-
})
|
|
63
|
+
tx = createMagicEdenExchangeTransaction(txData)
|
|
106
64
|
break
|
|
107
65
|
default:
|
|
108
66
|
// SOL and Token tx
|
|
109
|
-
tx =
|
|
110
|
-
from,
|
|
111
|
-
to,
|
|
112
|
-
amount,
|
|
113
|
-
recentBlockhash,
|
|
114
|
-
tokenMintAddress,
|
|
115
|
-
destinationAddressType,
|
|
116
|
-
isAssociatedTokenAccountActive,
|
|
117
|
-
fromTokenAddresses,
|
|
118
|
-
instructions,
|
|
119
|
-
feePayer,
|
|
120
|
-
})
|
|
67
|
+
tx = createTokenTransaction(txData)
|
|
121
68
|
break
|
|
122
69
|
}
|
|
70
|
+
return tx
|
|
71
|
+
}
|
|
123
72
|
|
|
124
|
-
|
|
125
|
-
Transaction.
|
|
126
|
-
|
|
127
|
-
|
|
73
|
+
const createDelegateTransaction = ({ address, amount, pool, recentBlockhash, seed }) =>
|
|
74
|
+
Transaction.createStakeAccountTransaction({
|
|
75
|
+
address,
|
|
76
|
+
amount,
|
|
77
|
+
recentBlockhash,
|
|
78
|
+
seed,
|
|
79
|
+
pool,
|
|
80
|
+
})
|
|
128
81
|
|
|
129
|
-
|
|
130
|
-
|
|
82
|
+
const createUndelegateTransaction = ({ address, recentBlockhash, stakeAddresses }) =>
|
|
83
|
+
Transaction.undelegate({
|
|
84
|
+
address,
|
|
85
|
+
recentBlockhash,
|
|
86
|
+
stakeAddresses,
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
const createWithdrawTransaction = ({ address, amount, recentBlockhash, stakeAddresses }) =>
|
|
90
|
+
Transaction.withdraw({
|
|
91
|
+
address,
|
|
92
|
+
amount,
|
|
93
|
+
recentBlockhash,
|
|
94
|
+
stakeAddresses,
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
const createMagicEdenInitializeEscrowTransaction = ({
|
|
98
|
+
escrowAddress,
|
|
99
|
+
escrowBump,
|
|
100
|
+
initializerDepositTokenAddress,
|
|
101
|
+
recentBlockhash,
|
|
102
|
+
takerAmount,
|
|
103
|
+
initializerAddress,
|
|
104
|
+
}) =>
|
|
105
|
+
Transaction.magicEdenInitializeEscrow({
|
|
106
|
+
escrowAddress,
|
|
107
|
+
escrowBump,
|
|
108
|
+
initializerAddress,
|
|
109
|
+
initializerDepositTokenAddress,
|
|
110
|
+
recentBlockhash,
|
|
111
|
+
takerAmount,
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
const createMagicEdenCancelEscrowTransaction = ({
|
|
115
|
+
escrowAddress,
|
|
116
|
+
initializerAddress,
|
|
117
|
+
initializerDepositTokenAddress,
|
|
118
|
+
pdaAddress,
|
|
119
|
+
recentBlockhash,
|
|
120
|
+
}) =>
|
|
121
|
+
Transaction.magicEdenCancelEscrow({
|
|
122
|
+
escrowAddress,
|
|
123
|
+
initializerAddress,
|
|
124
|
+
initializerDepositTokenAddress,
|
|
125
|
+
pdaAddress,
|
|
126
|
+
recentBlockhash,
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
const createMagicEdenExchangeTransaction = ({
|
|
130
|
+
creators,
|
|
131
|
+
escrowAddress,
|
|
132
|
+
expectedMintAddress,
|
|
133
|
+
expectedTakerAmount,
|
|
134
|
+
initializerAddress,
|
|
135
|
+
initializerDepositTokenAddress,
|
|
136
|
+
metadataAddress,
|
|
137
|
+
pdaAddress,
|
|
138
|
+
recentBlockhash,
|
|
139
|
+
takerAddress,
|
|
140
|
+
}) =>
|
|
141
|
+
Transaction.magicEdenExchange({
|
|
142
|
+
creators,
|
|
143
|
+
escrowAddress,
|
|
144
|
+
expectedMintAddress,
|
|
145
|
+
expectedTakerAmount,
|
|
146
|
+
initializerAddress,
|
|
147
|
+
initializerDepositTokenAddress,
|
|
148
|
+
metadataAddress,
|
|
149
|
+
pdaAddress,
|
|
150
|
+
recentBlockhash,
|
|
151
|
+
takerAddress,
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
const createTokenTransaction = ({
|
|
155
|
+
amount,
|
|
156
|
+
destinationAddressType,
|
|
157
|
+
feePayer,
|
|
158
|
+
from,
|
|
159
|
+
fromTokenAddresses,
|
|
160
|
+
instructions,
|
|
161
|
+
isAssociatedTokenAccountActive,
|
|
162
|
+
recentBlockhash,
|
|
163
|
+
to,
|
|
164
|
+
tokenMintAddress,
|
|
165
|
+
memo,
|
|
166
|
+
reference,
|
|
167
|
+
}) =>
|
|
168
|
+
new Transaction({
|
|
169
|
+
amount,
|
|
170
|
+
destinationAddressType,
|
|
171
|
+
feePayer,
|
|
172
|
+
from,
|
|
173
|
+
fromTokenAddresses,
|
|
174
|
+
instructions,
|
|
175
|
+
isAssociatedTokenAccountActive,
|
|
176
|
+
recentBlockhash,
|
|
177
|
+
to,
|
|
178
|
+
tokenMintAddress,
|
|
179
|
+
memo,
|
|
180
|
+
reference,
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
const createCloseAccountTransaction = ({ account, programId, recentBlockhash, walletPublicKey }) =>
|
|
184
|
+
Transaction.createCloseAccount({
|
|
185
|
+
account,
|
|
186
|
+
programId,
|
|
187
|
+
recentBlockhash,
|
|
188
|
+
walletPublicKey,
|
|
189
|
+
})
|