@exodus/solana-lib 1.4.3 → 1.6.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 +5 -7
- package/src/constants.js +2 -0
- package/src/fee-data/solana.js +6 -5
- package/src/helpers/transaction-strategy.js +25 -0
- package/src/index.js +2 -1
- package/src/tx/build-raw-transaction.js +62 -0
- package/src/tx/create-unsigned-tx.js +2 -2
- package/src/tx/index.js +1 -0
- package/src/tx/sign-unsigned-tx.js +6 -4
- package/src/versioned-transaction.js +45 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/solana-lib",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Exodus internal Solana low-level library",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"files": [
|
|
@@ -13,13 +13,11 @@
|
|
|
13
13
|
"access": "restricted"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@exodus/asset-lib": "^3.
|
|
17
|
-
"@exodus/assets": "^8.0.
|
|
18
|
-
"@exodus/assets-base": "^8.0.139",
|
|
16
|
+
"@exodus/asset-lib": "^3.7.1",
|
|
17
|
+
"@exodus/assets": "^8.0.74",
|
|
19
18
|
"@exodus/buffer-layout": "^1.2.0-exodus1",
|
|
20
|
-
"@exodus/models": "^8.
|
|
19
|
+
"@exodus/models": "^8.10.4",
|
|
21
20
|
"@exodus/solana-spl-token": "0.1.8-exodus.1",
|
|
22
|
-
"@exodus/web3-solana-utils": "^0.14.0",
|
|
23
21
|
"@project-serum/serum": "0.13.64",
|
|
24
22
|
"@solana/web3.js": "1.31.0",
|
|
25
23
|
"bn.js": "^4.11.0",
|
|
@@ -29,5 +27,5 @@
|
|
|
29
27
|
"lodash": "^4.17.11",
|
|
30
28
|
"tweetnacl": "^1.0.3"
|
|
31
29
|
},
|
|
32
|
-
"gitHead": "
|
|
30
|
+
"gitHead": "301d6e9222b3c0828c73cea460c94c9bbce878e6"
|
|
33
31
|
}
|
package/src/constants.js
CHANGED
package/src/fee-data/solana.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { FeeData } from '@exodus/asset-lib'
|
|
2
|
+
import assets from '@exodus/assets'
|
|
2
3
|
|
|
3
|
-
export default new FeeData(
|
|
4
|
-
{
|
|
4
|
+
export default new FeeData({
|
|
5
|
+
config: {
|
|
5
6
|
fee: '0.000005 SOL',
|
|
6
7
|
fuelThreshold: '0.000015 SOL',
|
|
7
8
|
},
|
|
8
|
-
'fee',
|
|
9
|
-
|
|
10
|
-
)
|
|
9
|
+
mainKey: 'fee',
|
|
10
|
+
currency: assets.solana.currency,
|
|
11
|
+
})
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Transaction, VersionedTransaction } from '..'
|
|
2
|
+
import { SUPPORTED_TRANSACTION_VERSIONS } from '../constants'
|
|
3
|
+
|
|
4
|
+
const isVersionedTransactionType = (transaction) => {
|
|
5
|
+
// new transaction types have a version field, either a string(legacy) or a number(>=0)
|
|
6
|
+
return transaction.version !== undefined
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const isVersionedTransactionTypeSupported = (transaction) => {
|
|
10
|
+
return SUPPORTED_TRANSACTION_VERSIONS.has(transaction.version)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const getTransactionStrategy = (transaction): VersionedTransaction | Transaction => {
|
|
14
|
+
if (isVersionedTransactionType(transaction)) {
|
|
15
|
+
if (isVersionedTransactionTypeSupported(transaction)) {
|
|
16
|
+
return VersionedTransaction
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
throw new Error(`unsupported transaction version: ${transaction.version}`)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return Transaction
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default getTransactionStrategy
|
package/src/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
|
|
3
|
-
export { buildRawTransaction } from '@exodus/web3-solana-utils'
|
|
4
3
|
export * from './constants'
|
|
5
4
|
export * from './encode'
|
|
6
5
|
export * from './keypair'
|
|
@@ -15,3 +14,5 @@ export {
|
|
|
15
14
|
} from './vendor'
|
|
16
15
|
export { default as Transaction } from './transaction'
|
|
17
16
|
export { U64 } from './helpers/spl-token'
|
|
17
|
+
export { default as getTransactionStrategy } from './helpers/transaction-strategy'
|
|
18
|
+
export { default as VersionedTransaction } from './versioned-transaction'
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import * as nacl from 'tweetnacl'
|
|
2
|
+
import { PACKET_DATA_SIZE } from '@solana/web3.js'
|
|
3
|
+
|
|
4
|
+
// Copied from:
|
|
5
|
+
// https://github.com/solana-labs/solana-web3.js/blob/42612c936d8d4ddbcb09dbb73db9e1aeaf6d8764/src/util/shortvec-encoding.ts#L15-L28.
|
|
6
|
+
function encodeLength(bytes: number[], length: number) {
|
|
7
|
+
let remainingLength = length
|
|
8
|
+
|
|
9
|
+
for (;;) {
|
|
10
|
+
let element = remainingLength & 0x7f
|
|
11
|
+
|
|
12
|
+
remainingLength >>= 7
|
|
13
|
+
if (remainingLength === 0) {
|
|
14
|
+
bytes.push(element)
|
|
15
|
+
break
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
element |= 0x80
|
|
19
|
+
bytes.push(element)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// As per:
|
|
24
|
+
// https://github.com/solana-labs/solana-web3.js/blob/61433de0d39686c6ad4f0b3cb5b95a68a058aa04/src/transaction.ts#L682
|
|
25
|
+
const MAX_SIGNATURES = 255
|
|
26
|
+
|
|
27
|
+
export const SIGNATURE_LENGTH = nacl.sign.signatureLength
|
|
28
|
+
|
|
29
|
+
export function buildRawTransaction(signData: Buffer, signatures: (Uint8Array | null)[]) {
|
|
30
|
+
const signatureCount: number[] = []
|
|
31
|
+
encodeLength(signatureCount, signatures.length)
|
|
32
|
+
|
|
33
|
+
const signaturesLength = signatureCount.length + signatures.length * SIGNATURE_LENGTH
|
|
34
|
+
const rawTransactionLength = signData.length + signaturesLength
|
|
35
|
+
|
|
36
|
+
if (signatures.length > MAX_SIGNATURES) {
|
|
37
|
+
throw Error(`Too many signatures: ${signatures.length} > ${MAX_SIGNATURES}`)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (rawTransactionLength > PACKET_DATA_SIZE) {
|
|
41
|
+
throw Error(`Transaction too large: ${rawTransactionLength} > ${PACKET_DATA_SIZE}`)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const rawTransaction = Buffer.alloc(rawTransactionLength)
|
|
45
|
+
Buffer.from(signatureCount).copy(rawTransaction)
|
|
46
|
+
|
|
47
|
+
signatures.forEach((signature, index) => {
|
|
48
|
+
if (signature === null) {
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (signature.length !== SIGNATURE_LENGTH) {
|
|
53
|
+
throw Error('Invalid signature length')
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
Buffer.from(signature).copy(rawTransaction, signatureCount.length + index * SIGNATURE_LENGTH)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
signData.copy(rawTransaction, signaturesLength)
|
|
60
|
+
|
|
61
|
+
return rawTransaction
|
|
62
|
+
}
|
|
@@ -38,8 +38,8 @@ export function createUnsignedTx({
|
|
|
38
38
|
txData: {
|
|
39
39
|
from,
|
|
40
40
|
to,
|
|
41
|
-
amount: amount ? amount.
|
|
42
|
-
fee: fee ? fee.
|
|
41
|
+
amount: amount ? amount.toBaseNumber() : null,
|
|
42
|
+
fee: fee ? fee.toBaseNumber() : null,
|
|
43
43
|
recentBlockhash,
|
|
44
44
|
// Tokens related:
|
|
45
45
|
tokenMintAddress,
|
package/src/tx/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { merge } from 'lodash'
|
|
|
2
2
|
import assets from '@exodus/assets'
|
|
3
3
|
import type { UnsignedTransaction, SignedTransaction } from '@exodus/models/lib/types'
|
|
4
4
|
|
|
5
|
-
import { Transaction } from '../'
|
|
5
|
+
import { Transaction, getTransactionStrategy } from '../'
|
|
6
6
|
|
|
7
7
|
export function signUnsignedTx(
|
|
8
8
|
unsignedTx: UnsignedTransaction,
|
|
@@ -30,9 +30,11 @@ export function signUnsignedTx(
|
|
|
30
30
|
|
|
31
31
|
// Signs plain tx.
|
|
32
32
|
const _signTx = ({ tx, privateKey }) => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
const _Transaction = getTransactionStrategy(tx)
|
|
34
|
+
|
|
35
|
+
_Transaction.sign(tx, privateKey)
|
|
36
|
+
const rawTx = _Transaction.serialize(tx)
|
|
37
|
+
const txId = _Transaction.getTxId(tx)
|
|
36
38
|
|
|
37
39
|
return { txId, rawTx }
|
|
38
40
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import base58 from 'bs58'
|
|
2
|
+
import { getKeyPairFromPrivateKey } from './keypair'
|
|
3
|
+
import { Account } from './vendor'
|
|
4
|
+
|
|
5
|
+
function getFirstSignature(tx) {
|
|
6
|
+
if (tx.signatures.length > 0) {
|
|
7
|
+
return tx.signatures[0]
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return null
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
class VersionedTx {
|
|
14
|
+
// tx is not supported from the vendored library (solana-lib/src/vendor).
|
|
15
|
+
// We also can't make any guarantees that Account from vendored lib with version X
|
|
16
|
+
// will be compatible with the tx built by an outside library with version Y.
|
|
17
|
+
static sign(tx, privateKey: Buffer | String, extraSigners: Account[] = []) {
|
|
18
|
+
if (!privateKey) {
|
|
19
|
+
throw new Error('Please provide a secretKey')
|
|
20
|
+
}
|
|
21
|
+
const { secretKey } = getKeyPairFromPrivateKey(privateKey)
|
|
22
|
+
const signers = [new Account(secretKey), ...extraSigners]
|
|
23
|
+
|
|
24
|
+
tx.sign(signers)
|
|
25
|
+
|
|
26
|
+
if (!(tx.signatures && tx.signatures.length)) {
|
|
27
|
+
throw new Error('!Signature')
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static serialize(tx) {
|
|
32
|
+
const serializedTx = tx.serialize()
|
|
33
|
+
return Buffer.from(serializedTx).toString('base64')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static getTxId(tx) {
|
|
37
|
+
const signature = getFirstSignature(tx)
|
|
38
|
+
if (signature === null) {
|
|
39
|
+
throw new Error('Cannot get transaction ID of unsigned transaction')
|
|
40
|
+
}
|
|
41
|
+
return base58.encode(signature)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export default VersionedTx
|