@exodus/solana-lib 2.3.0 → 3.0.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 +4 -3
- package/src/index.js +1 -0
- package/src/msg/index.js +2 -0
- package/src/msg/sign-message-deprecated.js +20 -0
- package/src/msg/sign-message.js +19 -0
- package/src/{tx/sign-message.js → msg/validation.js} +16 -17
- package/src/tx/create-and-sign-tx.js +1 -1
- package/src/tx/decode-tx-instructions.js +1 -1
- package/src/tx/index.js +0 -1
- package/src/tx/sign-unsigned-tx.js +31 -19
- package/src/vendor/transaction.js +0 -17
- package/src/tx/async-account.js +0 -38
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/solana-lib",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Exodus internal Solana low-level library",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"files": [
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
"@exodus/currency": "^2.3.2",
|
|
24
24
|
"@exodus/key-utils": "^3.1.0",
|
|
25
25
|
"@exodus/models": "^10.1.0",
|
|
26
|
-
"@project-serum
|
|
26
|
+
"@exodus/project-serum-serum": "0.13.64-exodus.0",
|
|
27
|
+
"@exodus/solana-web3.js": "^1.63.1-exodus.3",
|
|
27
28
|
"bn.js": "^4.11.0",
|
|
28
29
|
"borsh": "^0.7.0",
|
|
29
30
|
"bs58": "^4.0.1",
|
|
@@ -39,5 +40,5 @@
|
|
|
39
40
|
"@solana/web3.js": "^1.90.0",
|
|
40
41
|
"bip39": "^2.6.0"
|
|
41
42
|
},
|
|
42
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "30fdc2a936b6776866467baf926c899e9a236beb"
|
|
43
44
|
}
|
package/src/index.js
CHANGED
package/src/msg/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import assert from 'assert'
|
|
2
|
+
import nacl from 'tweetnacl'
|
|
3
|
+
import bs58 from 'bs58'
|
|
4
|
+
|
|
5
|
+
import { isTransactionMessage } from './validation'
|
|
6
|
+
import { getKeyPairFromPrivateKey } from '../keypair'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @deprecated please use messageSigner
|
|
10
|
+
*/
|
|
11
|
+
export function signMessage({ message, privateKey }) {
|
|
12
|
+
const { secretKey } = getKeyPairFromPrivateKey(privateKey)
|
|
13
|
+
const messageBuffer = bs58.decode(message)
|
|
14
|
+
assert(
|
|
15
|
+
!isTransactionMessage(messageBuffer),
|
|
16
|
+
'attempted to sign transaction using message signing'
|
|
17
|
+
)
|
|
18
|
+
const signature = nacl.sign.detached(messageBuffer, secretKey)
|
|
19
|
+
return bs58.encode(signature)
|
|
20
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import assert from 'minimalistic-assert'
|
|
2
|
+
import * as nacl from 'tweetnacl'
|
|
3
|
+
|
|
4
|
+
import { isTransactionMessage } from './validation'
|
|
5
|
+
|
|
6
|
+
export const signMessageNew = async ({ privateKey, message }) => {
|
|
7
|
+
const { rawMessage } = message
|
|
8
|
+
assert(Buffer.isBuffer(rawMessage), `rawMessage must be buffer`)
|
|
9
|
+
assert(
|
|
10
|
+
!isTransactionMessage(rawMessage),
|
|
11
|
+
`malicious message signing request, was a transaction message`
|
|
12
|
+
)
|
|
13
|
+
assert(
|
|
14
|
+
Buffer.isBuffer(privateKey) || privateKey instanceof Uint8Array,
|
|
15
|
+
`privateKey is not a Buffer or Uint8Array`
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
return Buffer.from(nacl.sign.detached(rawMessage, privateKey))
|
|
19
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import nacl from 'tweetnacl'
|
|
3
|
-
import bs58 from 'bs58'
|
|
4
|
-
|
|
5
|
-
import { Message } from '../vendor/message'
|
|
6
|
-
import { getKeyPairFromPrivateKey } from '../keypair'
|
|
1
|
+
import { Message } from '@exodus/solana-web3.js'
|
|
7
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Checks if its contains a legacy message.
|
|
5
|
+
* @param {Uint8Array} data
|
|
6
|
+
* @returns {boolean}
|
|
7
|
+
*/
|
|
8
8
|
function isLegacyMessage(data) {
|
|
9
9
|
try {
|
|
10
10
|
const message = Message.from(data)
|
|
@@ -15,6 +15,11 @@ function isLegacyMessage(data) {
|
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Checks if its contains a versioned message.
|
|
20
|
+
* @param {Uint8Array} data
|
|
21
|
+
* @returns {boolean}
|
|
22
|
+
*/
|
|
18
23
|
function isVersionedMessage(data) {
|
|
19
24
|
if (data.length > 1) {
|
|
20
25
|
// We deploy a heuristic to detect transaction messages.
|
|
@@ -27,18 +32,12 @@ function isVersionedMessage(data) {
|
|
|
27
32
|
return false
|
|
28
33
|
}
|
|
29
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Check whether a message contains a transaction message.
|
|
37
|
+
* @param {Uint8Array} data
|
|
38
|
+
* @returns {boolean}
|
|
39
|
+
*/
|
|
30
40
|
export function isTransactionMessage(data) {
|
|
31
41
|
const messageBuffer = Buffer.from(data)
|
|
32
42
|
return isLegacyMessage(messageBuffer) || isVersionedMessage(messageBuffer)
|
|
33
43
|
}
|
|
34
|
-
|
|
35
|
-
export default function signMessage({ message, privateKey }) {
|
|
36
|
-
const { secretKey } = getKeyPairFromPrivateKey(privateKey)
|
|
37
|
-
const messageBuffer = bs58.decode(message)
|
|
38
|
-
assert(
|
|
39
|
-
!isTransactionMessage(messageBuffer),
|
|
40
|
-
'attempted to sign transaction using message signing'
|
|
41
|
-
)
|
|
42
|
-
const signature = nacl.sign.detached(messageBuffer, secretKey)
|
|
43
|
-
return bs58.encode(signature)
|
|
44
|
-
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createUnsignedTx } from './create-unsigned-tx'
|
|
2
2
|
import { signUnsignedTx } from './sign-unsigned-tx'
|
|
3
3
|
|
|
4
|
-
export function createAndSignTx(input, privateKey) {
|
|
4
|
+
export async function createAndSignTx(input, privateKey) {
|
|
5
5
|
const unsignedTx = createUnsignedTx(input)
|
|
6
6
|
return signUnsignedTx(unsignedTx, privateKey)
|
|
7
7
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID } from '../helpers/spl-token'
|
|
2
|
-
import { MARKETS, TokenInstructions } from '@project-serum
|
|
2
|
+
import { MARKETS, TokenInstructions } from '@exodus/project-serum-serum'
|
|
3
3
|
import * as BufferLayout from '@exodus/buffer-layout'
|
|
4
4
|
|
|
5
5
|
import { SystemInstruction, SystemProgram } from './../vendor'
|
package/src/tx/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import assert from 'minimalistic-assert'
|
|
2
|
+
import * as nacl from 'tweetnacl'
|
|
3
|
+
import bs58 from 'bs58'
|
|
2
4
|
|
|
3
5
|
import { prepareForSigning } from './prepare-for-signing'
|
|
4
6
|
import { getKeyPairFromPrivateKey } from '../keypair'
|
|
5
|
-
import {
|
|
6
|
-
import { AsyncSignerAccount } from './async-account'
|
|
7
|
+
import { PublicKey } from '../vendor'
|
|
7
8
|
import { extractTransaction, isVersionedTransaction } from './common'
|
|
8
9
|
|
|
9
10
|
/**
|
|
@@ -17,49 +18,60 @@ export async function signUnsignedTxWithSigner(unsignedTx, signer) {
|
|
|
17
18
|
|
|
18
19
|
const tx = prepareForSigning(unsignedTx)
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
await account.updatePublicKey()
|
|
22
|
-
await _signTx({ tx, account })
|
|
21
|
+
await _signTx({ tx, signer })
|
|
23
22
|
|
|
24
23
|
return extractTransaction({ tx })
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
export function signUnsignedTx(unsignedTx, privateKey) {
|
|
26
|
+
export async function signUnsignedTx(unsignedTx, privateKey) {
|
|
28
27
|
assert(privateKey, 'Please provide a secretKey')
|
|
29
28
|
|
|
30
29
|
const tx = prepareForSigning(unsignedTx)
|
|
31
30
|
|
|
32
|
-
const { secretKey } = getKeyPairFromPrivateKey(privateKey)
|
|
33
|
-
const
|
|
34
|
-
|
|
31
|
+
const { secretKey, publicKey } = getKeyPairFromPrivateKey(privateKey)
|
|
32
|
+
const signer = {
|
|
33
|
+
getPublicKey: () => publicKey,
|
|
34
|
+
sign: ({ data }) => nacl.sign.detached(data, secretKey),
|
|
35
|
+
}
|
|
36
|
+
await _signTx({ tx, signer })
|
|
35
37
|
|
|
36
38
|
return extractTransaction({ tx })
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
// Signs plain tx.
|
|
40
|
-
const _signTx = ({ tx,
|
|
42
|
+
const _signTx = async ({ tx, signer }) => {
|
|
43
|
+
const publicKey = new PublicKey(bs58.encode(Buffer.from(await signer.getPublicKey())))
|
|
44
|
+
|
|
41
45
|
if (isVersionedTransaction(tx)) {
|
|
42
46
|
// VersionedTransaction
|
|
43
|
-
return tx
|
|
47
|
+
return _signVersionedTransaction({ tx, signer, publicKey })
|
|
44
48
|
}
|
|
45
|
-
|
|
46
49
|
// Legacy Transactions
|
|
47
50
|
|
|
48
51
|
// Some transactions that we construct internally are technically not complete.
|
|
49
52
|
// They don't contain the empty signature slot for the public key.
|
|
50
|
-
const foundEmptySignatureSlot = tx.signatures.find(({ publicKey }) =>
|
|
51
|
-
|
|
53
|
+
const foundEmptySignatureSlot = tx.signatures.find(({ publicKey: _publicKey }) =>
|
|
54
|
+
_publicKey.equals(publicKey)
|
|
52
55
|
)
|
|
53
56
|
if (!foundEmptySignatureSlot) {
|
|
54
57
|
// We could use `setSigners` but maybe this is more robust?
|
|
55
58
|
tx.signatures.push({
|
|
56
|
-
publicKey
|
|
59
|
+
publicKey,
|
|
57
60
|
signature: null,
|
|
58
61
|
})
|
|
59
62
|
}
|
|
60
63
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
return _signLegacyTransaction({ tx, signer, publicKey })
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const _signVersionedTransaction = async ({ tx, signer, publicKey }) => {
|
|
68
|
+
const messageData = tx.message.serialize()
|
|
69
|
+
const signature = await signer.sign({ data: messageData })
|
|
70
|
+
tx.addSignature(publicKey, signature)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const _signLegacyTransaction = async ({ tx, signer, publicKey }) => {
|
|
74
|
+
const messageData = tx.compileMessage().serialize()
|
|
75
|
+
const signature = await signer.sign({ data: messageData })
|
|
76
|
+
tx.addSignature(publicKey, signature)
|
|
65
77
|
}
|
|
@@ -21,8 +21,6 @@ import * as shortvec from './utils/shortvec-encoding'
|
|
|
21
21
|
const DEFAULT_SIGNATURE = Buffer.alloc(64).fill(0)
|
|
22
22
|
const SIGNATURE_LENGTH = 64
|
|
23
23
|
|
|
24
|
-
const isAsyncAccount = (signer) => signer.sign && signer.publicKey && signer.updatePublicKey
|
|
25
|
-
|
|
26
24
|
/**
|
|
27
25
|
* Account metadata used to define instructions
|
|
28
26
|
*
|
|
@@ -436,21 +434,6 @@ export class Transaction {
|
|
|
436
434
|
})
|
|
437
435
|
|
|
438
436
|
const signData = message.serialize()
|
|
439
|
-
|
|
440
|
-
const isAsyncSign = signers.some(isAsyncAccount)
|
|
441
|
-
if (isAsyncSign) {
|
|
442
|
-
return Promise.all(
|
|
443
|
-
signers.map(async (signer) => ({
|
|
444
|
-
signature: isAsyncAccount(signer)
|
|
445
|
-
? await signer.sign(signData) // Promise
|
|
446
|
-
: nacl.sign.detached(signData, signer.secretKey),
|
|
447
|
-
publicKey: signer.publicKey,
|
|
448
|
-
}))
|
|
449
|
-
).then((signatures) =>
|
|
450
|
-
signatures.forEach(({ publicKey, signature }) => this.addSignature(publicKey, signature))
|
|
451
|
-
)
|
|
452
|
-
}
|
|
453
|
-
|
|
454
437
|
signers.forEach((signer) => {
|
|
455
438
|
const signature = nacl.sign.detached(signData, signer.secretKey)
|
|
456
439
|
this.addSignature(signer.publicKey, signature)
|
package/src/tx/async-account.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { PublicKey } from '../vendor/publickey'
|
|
2
|
-
|
|
3
|
-
export class AsyncSignerAccount {
|
|
4
|
-
#publicKey
|
|
5
|
-
#asyncSigner
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Create a new AsyncSignerAccount object
|
|
9
|
-
*
|
|
10
|
-
* @param asyncSigner A signer object: `{ sign, getPublicKey }`
|
|
11
|
-
*/
|
|
12
|
-
constructor(asyncSigner) {
|
|
13
|
-
if (!asyncSigner) throw new Error('please provide a signer object to async signer')
|
|
14
|
-
|
|
15
|
-
this.#asyncSigner = asyncSigner
|
|
16
|
-
this.updatePublicKey().catch((err) =>
|
|
17
|
-
console.error('error getting public key from signer', err)
|
|
18
|
-
)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
get publicKey() {
|
|
22
|
-
if (!this.#publicKey) throw new Error('public key not yet available in async signer')
|
|
23
|
-
return this.#publicKey
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
get secretKey() {
|
|
27
|
-
throw new Error('secret key not available from async signer')
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
sign = async (signData) => this.#asyncSigner.sign({ data: signData })
|
|
31
|
-
|
|
32
|
-
updatePublicKey = async () => {
|
|
33
|
-
if (!this.#publicKey) {
|
|
34
|
-
const publicKey = await this.#asyncSigner.getPublicKey()
|
|
35
|
-
this.#publicKey = new PublicKey(publicKey)
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|