@exodus/solana-lib 1.2.13 → 1.2.14

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.
Files changed (60) hide show
  1. package/lib/constants.js +19 -0
  2. package/lib/encode.js +67 -0
  3. package/lib/fee-data/index.js +15 -0
  4. package/lib/fee-data/solana.js +14 -0
  5. package/lib/helpers/spl-token.js +122 -0
  6. package/lib/helpers/tokenTransfer.js +78 -0
  7. package/lib/index.js +88 -0
  8. package/lib/keypair.js +38 -0
  9. package/lib/tokens.js +21 -0
  10. package/lib/transaction.js +338 -0
  11. package/lib/tx/create-and-sign-tx.js +15 -0
  12. package/{src → lib}/tx/create-unsigned-tx.js +18 -11
  13. package/lib/tx/index.js +53 -0
  14. package/lib/tx/parse-unsigned-tx.js +55 -0
  15. package/lib/tx/sign-unsigned-tx.js +90 -0
  16. package/lib/vendor/account.js +48 -0
  17. package/lib/vendor/index.js +113 -0
  18. package/lib/vendor/instruction.js +48 -0
  19. package/lib/vendor/message.js +167 -0
  20. package/lib/vendor/nonce-account.js +56 -0
  21. package/lib/vendor/publickey.js +211 -0
  22. package/lib/vendor/stake-program.js +476 -0
  23. package/lib/vendor/system-program.js +640 -0
  24. package/lib/vendor/sysvar.js +19 -0
  25. package/lib/vendor/transaction.js +594 -0
  26. package/lib/vendor/utils/blockhash.js +1 -0
  27. package/lib/vendor/utils/fee-calculator.js +25 -0
  28. package/lib/vendor/utils/layout.js +97 -0
  29. package/lib/vendor/utils/shortvec-encoding.js +41 -0
  30. package/lib/vendor/utils/to-buffer.js +18 -0
  31. package/package.json +4 -5
  32. package/src/constants.js +0 -12
  33. package/src/encode.js +0 -57
  34. package/src/fee-data/index.js +0 -1
  35. package/src/fee-data/solana.js +0 -9
  36. package/src/helpers/spl-token.js +0 -108
  37. package/src/helpers/tokenTransfer.js +0 -72
  38. package/src/index.js +0 -9
  39. package/src/keypair.js +0 -32
  40. package/src/tokens.js +0 -19
  41. package/src/transaction.js +0 -292
  42. package/src/tx/create-and-sign-tx.js +0 -8
  43. package/src/tx/index.js +0 -4
  44. package/src/tx/parse-unsigned-tx.js +0 -41
  45. package/src/tx/sign-unsigned-tx.js +0 -78
  46. package/src/vendor/account.js +0 -38
  47. package/src/vendor/index.js +0 -9
  48. package/src/vendor/instruction.js +0 -46
  49. package/src/vendor/message.js +0 -216
  50. package/src/vendor/nonce-account.js +0 -46
  51. package/src/vendor/publickey.js +0 -212
  52. package/src/vendor/stake-program.js +0 -527
  53. package/src/vendor/system-program.js +0 -782
  54. package/src/vendor/sysvar.js +0 -16
  55. package/src/vendor/transaction.js +0 -594
  56. package/src/vendor/utils/blockhash.js +0 -6
  57. package/src/vendor/utils/fee-calculator.js +0 -17
  58. package/src/vendor/utils/layout.js +0 -80
  59. package/src/vendor/utils/shortvec-encoding.js +0 -30
  60. package/src/vendor/utils/to-buffer.js +0 -9
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getAlloc = getAlloc;
7
+ exports.lockup = exports.authorized = exports.rustString = exports.uint64 = exports.publicKey = void 0;
8
+
9
+ var BufferLayout = _interopRequireWildcard(require("@exodus/buffer-layout"));
10
+
11
+ function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
12
+
13
+ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
14
+
15
+ /**
16
+ * Layout for a public key
17
+ */
18
+ const publicKey = (property = 'publicKey') => {
19
+ return BufferLayout.blob(32, property);
20
+ };
21
+ /**
22
+ * Layout for a 64bit unsigned value
23
+ */
24
+
25
+
26
+ exports.publicKey = publicKey;
27
+
28
+ const uint64 = (property = 'uint64') => {
29
+ return BufferLayout.blob(8, property);
30
+ };
31
+ /**
32
+ * Layout for a Rust String type
33
+ */
34
+
35
+
36
+ exports.uint64 = uint64;
37
+
38
+ const rustString = (property = 'string') => {
39
+ const rsl = BufferLayout.struct([BufferLayout.u32('length'), BufferLayout.u32('lengthPadding'), BufferLayout.blob(BufferLayout.offset(BufferLayout.u32(), -8), 'chars')], property);
40
+
41
+ const _decode = rsl.decode.bind(rsl);
42
+
43
+ const _encode = rsl.encode.bind(rsl);
44
+
45
+ rsl.decode = (buffer, offset) => {
46
+ const data = _decode(buffer, offset);
47
+
48
+ return data.chars.toString('utf8');
49
+ };
50
+
51
+ rsl.encode = (str, buffer, offset) => {
52
+ const data = {
53
+ chars: Buffer.from(str, 'utf8')
54
+ };
55
+ return _encode(data, buffer, offset);
56
+ };
57
+
58
+ rsl.alloc = str => {
59
+ return BufferLayout.u32().span + BufferLayout.u32().span + Buffer.from(str, 'utf8').length;
60
+ };
61
+
62
+ return rsl;
63
+ };
64
+ /**
65
+ * Layout for an Authorized object
66
+ */
67
+
68
+
69
+ exports.rustString = rustString;
70
+
71
+ const authorized = (property = 'authorized') => {
72
+ return BufferLayout.struct([publicKey('staker'), publicKey('withdrawer')], property);
73
+ };
74
+ /**
75
+ * Layout for a Lockup object
76
+ */
77
+
78
+
79
+ exports.authorized = authorized;
80
+
81
+ const lockup = (property = 'lockup') => {
82
+ return BufferLayout.struct([BufferLayout.ns64('unixTimestamp'), BufferLayout.ns64('epoch'), publicKey('custodian')], property);
83
+ };
84
+
85
+ exports.lockup = lockup;
86
+
87
+ function getAlloc(type, fields) {
88
+ let alloc = 0;
89
+ type.layout.fields.forEach(item => {
90
+ if (item.span >= 0) {
91
+ alloc += item.span;
92
+ } else if (typeof item.alloc === 'function') {
93
+ alloc += item.alloc(fields[item.property]);
94
+ }
95
+ });
96
+ return alloc;
97
+ }
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.decodeLength = decodeLength;
7
+ exports.encodeLength = encodeLength;
8
+
9
+ function decodeLength(bytes) {
10
+ let len = 0;
11
+ let size = 0;
12
+
13
+ for (;;) {
14
+ let elem = bytes.shift();
15
+ len |= (elem & 0x7f) << size * 7;
16
+ size += 1;
17
+
18
+ if ((elem & 0x80) === 0) {
19
+ break;
20
+ }
21
+ }
22
+
23
+ return len;
24
+ }
25
+
26
+ function encodeLength(bytes, len) {
27
+ let remLen = len;
28
+
29
+ for (;;) {
30
+ let elem = remLen & 0x7f;
31
+ remLen >>= 7;
32
+
33
+ if (remLen === 0) {
34
+ bytes.push(elem);
35
+ break;
36
+ } else {
37
+ elem |= 0x80;
38
+ bytes.push(elem);
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.toBuffer = void 0;
7
+
8
+ const toBuffer = arr => {
9
+ if (arr instanceof Buffer) {
10
+ return arr;
11
+ } else if (arr instanceof Uint8Array) {
12
+ return Buffer.from(arr.buffer, arr.byteOffset, arr.byteLength);
13
+ } else {
14
+ return Buffer.from(arr);
15
+ }
16
+ };
17
+
18
+ exports.toBuffer = toBuffer;
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@exodus/solana-lib",
3
- "version": "1.2.13",
3
+ "version": "1.2.14",
4
4
  "description": "Exodus internal Solana low-level library",
5
- "main": "src/index.js",
5
+ "main": "lib/index.js",
6
6
  "files": [
7
- "src/",
7
+ "lib/",
8
8
  "!src/__tests__"
9
9
  ],
10
10
  "author": "Exodus",
@@ -22,6 +22,5 @@
22
22
  "create-hash": "^1.1.3",
23
23
  "lodash": "^4.17.11",
24
24
  "tweetnacl": "^1.0.3"
25
- },
26
- "gitHead": "df87ac51e1f8ff2d14664a0707166cdc3ccd9a8d"
25
+ }
27
26
  }
package/src/constants.js DELETED
@@ -1,12 +0,0 @@
1
- import { PublicKey, SystemProgram, StakeProgram } from './vendor'
2
-
3
- export const SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID = new PublicKey(
4
- 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL'
5
- )
6
- export const SYSTEM_PROGRAM_ID = SystemProgram.programId
7
-
8
- export const STAKE_PROGRAM_ID = StakeProgram.programId
9
-
10
- export const TOKEN_PROGRAM_ID = new PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA')
11
-
12
- export const SEED = 'stake:0'
package/src/encode.js DELETED
@@ -1,57 +0,0 @@
1
- // @flow
2
- import { PublicKey, StakeProgram } from './vendor'
3
- import { SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID, TOKEN_PROGRAM_ID, SEED } from './constants'
4
- import { getPublicKey } from './keypair'
5
- import bs58 from 'bs58'
6
- import BN from 'bn.js'
7
-
8
- export function getAddressFromPublicKey(publicKey: string | Buffer): string {
9
- return bs58.encode(Buffer.from(publicKey, 'hex'))
10
- }
11
-
12
- export function getAddressFromPrivateKey(privateKey: string | Buffer): string {
13
- return getAddressFromPublicKey(getPublicKey(privateKey))
14
- }
15
-
16
- export function isValidAddress(address: string): boolean {
17
- try {
18
- // assume base 58 encoding by default
19
- const decoded = bs58.decode(address)
20
- if (decoded.length !== 32) {
21
- return false
22
- }
23
- const _bn = new BN(decoded)
24
- if (_bn.byteLength() > 32) {
25
- return false
26
- }
27
- return true
28
- } catch (e) {
29
- return false
30
- }
31
- }
32
-
33
- // doc: https://spl.solana.com/associated-token-account (HACK: refactored to sync)
34
- export function findAssociatedTokenAddress(
35
- walletAddress: string,
36
- tokenMintAddress: string
37
- ): string {
38
- walletAddress = new PublicKey(walletAddress)
39
- tokenMintAddress = new PublicKey(tokenMintAddress)
40
- return PublicKey.findProgramAddress(
41
- [walletAddress.toBuffer(), TOKEN_PROGRAM_ID.toBuffer(), tokenMintAddress.toBuffer()],
42
- SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID
43
- )[0].toBase58() // returns encoded PublicKey
44
- }
45
-
46
- export function createStakeAddress(walletAddress: string, seed = SEED): string {
47
- const fromPubkey = new PublicKey(walletAddress)
48
-
49
- const newAccountPubkey = PublicKey.createWithSeed(
50
- // HACK: refactored to sync
51
- fromPubkey,
52
- seed,
53
- StakeProgram.programId
54
- )
55
-
56
- return newAccountPubkey.toBase58()
57
- }
@@ -1 +0,0 @@
1
- export { default as solana } from './solana'
@@ -1,9 +0,0 @@
1
- import { FeeData } from '@exodus/asset-lib'
2
-
3
- export default new FeeData(
4
- {
5
- fee: '0.000005 SOL',
6
- },
7
- 'fee',
8
- 'solana'
9
- )
@@ -1,108 +0,0 @@
1
- import assert from 'assert'
2
- import BN from 'bn.js'
3
- import * as BufferLayout from '@exodus/buffer-layout'
4
- import { Account, PublicKey, TransactionInstruction } from '../vendor'
5
- import * as Layout from '../vendor/utils/layout'
6
-
7
- // Extracted from https://github.com/ExodusMovement/solana-spl-token/blob/master/src/index.js#L263
8
-
9
- /**
10
- * 64-bit value
11
- */
12
- export class U64 extends BN {
13
- /**
14
- * Convert to Buffer representation
15
- */
16
- toBuffer(): typeof Buffer {
17
- const a = super.toArray().reverse()
18
- const b = Buffer.from(a)
19
- if (b.length === 8) {
20
- return b
21
- }
22
- assert(b.length < 8, 'u64 too large')
23
-
24
- const zeroPad = Buffer.alloc(8)
25
- b.copy(zeroPad)
26
- return zeroPad
27
- }
28
-
29
- /**
30
- * Construct a u64 from Buffer representation
31
- */
32
- static fromBuffer(buffer: typeof Buffer): U64 {
33
- assert(buffer.length === 8, `Invalid buffer length: ${buffer.length}`)
34
- return new U64(
35
- [...buffer]
36
- .reverse()
37
- .map((i) => `00${i.toString(16)}`.slice(-2))
38
- .join(''),
39
- 16
40
- )
41
- }
42
- }
43
-
44
- const u64 = U64 // alias
45
-
46
- /**
47
- * An ERC20-like Token
48
- */
49
- export class Token {
50
- /**
51
- * Construct a Transfer instruction
52
- *
53
- * @param programId SPL Token program account
54
- * @param source Source account
55
- * @param destination Destination account
56
- * @param owner Owner of the source account
57
- * @param multiSigners Signing accounts if `authority` is a multiSig
58
- * @param amount Number of tokens to transfer
59
- */
60
- static createTransferInstruction(
61
- programId: PublicKey,
62
- source: PublicKey,
63
- destination: PublicKey,
64
- owner: PublicKey,
65
- multiSigners: Array<Account>,
66
- amount: number | u64
67
- ): TransactionInstruction {
68
- const dataLayout = BufferLayout.struct([
69
- BufferLayout.u8('instruction'),
70
- Layout.uint64('amount'),
71
- ])
72
-
73
- const data = Buffer.alloc(dataLayout.span)
74
- dataLayout.encode(
75
- {
76
- instruction: 3, // Transfer instruction
77
- amount: new U64(amount).toBuffer(),
78
- },
79
- data
80
- )
81
-
82
- let keys = [
83
- { pubkey: source, isSigner: false, isWritable: true },
84
- { pubkey: destination, isSigner: false, isWritable: true },
85
- ]
86
- if (multiSigners.length === 0) {
87
- keys.push({
88
- pubkey: owner,
89
- isSigner: true,
90
- isWritable: false,
91
- })
92
- } else {
93
- keys.push({ pubkey: owner, isSigner: false, isWritable: false })
94
- multiSigners.forEach((signer) =>
95
- keys.push({
96
- pubkey: signer.publicKey,
97
- isSigner: true,
98
- isWritable: false,
99
- })
100
- )
101
- }
102
- return new TransactionInstruction({
103
- keys,
104
- programId: programId,
105
- data,
106
- })
107
- }
108
- }
@@ -1,72 +0,0 @@
1
- import { Token } from './spl-token'
2
- import { PublicKey, TransactionInstruction, SystemProgram, SYSVAR_RENT_PUBKEY } from '../vendor'
3
- import { SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID, TOKEN_PROGRAM_ID } from '../constants'
4
- import { findAssociatedTokenAddress } from '../encode'
5
-
6
- // https://github.com/paul-schaaf/spl-token-ui/blob/main/src/solana/token/associatedToken.ts#L59
7
- export const createAssociatedTokenAccount = (
8
- senderAddress: string,
9
- tokenMintAddress: string,
10
- ownerAddress: string // destination SOL address
11
- ) => {
12
- const associatedTokenAccountPublicKey = new PublicKey(
13
- findAssociatedTokenAddress(ownerAddress, tokenMintAddress)
14
- )
15
-
16
- const feePayerPublicKey = new PublicKey(senderAddress)
17
- const ownerPublicKey = new PublicKey(ownerAddress)
18
- const tokenMintPublicKey = new PublicKey(tokenMintAddress)
19
-
20
- const ix = createIx(
21
- feePayerPublicKey, // feePayer
22
- associatedTokenAccountPublicKey,
23
- ownerPublicKey,
24
- tokenMintPublicKey
25
- )
26
-
27
- return ix // returns the instruction
28
- }
29
-
30
- function createIx(
31
- funderPubkey: PublicKey,
32
- associatedTokenAccountPublicKey: PublicKey,
33
- ownerPublicKey: PublicKey,
34
- tokenMintPublicKey: PublicKey
35
- ) {
36
- return new TransactionInstruction({
37
- programId: SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID,
38
- data: Buffer.from([]),
39
- keys: [
40
- { pubkey: funderPubkey, isSigner: true, isWritable: true },
41
- {
42
- pubkey: associatedTokenAccountPublicKey,
43
- isSigner: false,
44
- isWritable: true,
45
- },
46
- { pubkey: ownerPublicKey, isSigner: false, isWritable: false },
47
- { pubkey: tokenMintPublicKey, isSigner: false, isWritable: false },
48
- { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
49
- { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
50
- { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },
51
- ],
52
- })
53
- }
54
-
55
- // https://github.com/paul-schaaf/spl-token-ui/blob/main/src/solana/token/editing.ts#L211
56
- export const createTokenTransferInstruction = (owner, fromTokenAddress, to, amount) => {
57
- const sourcePubkey = new PublicKey(fromTokenAddress) // the token ADDRESS needed!
58
- const destinationPubkey = new PublicKey(to)
59
- console.log(`destination token address: ${destinationPubkey.toBase58()}`)
60
- const ownerAccountOrWalletPublicKey = new PublicKey(owner) // the only native SOL address
61
-
62
- const transferIx = Token.createTransferInstruction(
63
- TOKEN_PROGRAM_ID,
64
- sourcePubkey,
65
- destinationPubkey,
66
- ownerAccountOrWalletPublicKey,
67
- [],
68
- amount
69
- )
70
-
71
- return transferIx
72
- }
package/src/index.js DELETED
@@ -1,9 +0,0 @@
1
- // @flow
2
-
3
- export * from './constants'
4
- export * from './encode'
5
- export * from './keypair'
6
- export * from './tx'
7
- export { StakeInstruction } from './vendor'
8
- export { default as tokens } from './tokens'
9
- export { default as Transaction } from './transaction'
package/src/keypair.js DELETED
@@ -1,32 +0,0 @@
1
- // @flow
2
- import nacl from 'tweetnacl'
3
-
4
- export function getKeyPairFromPrivateKey(privateKey: string | Buffer): Object {
5
- const { publicKey, secretKey } = nacl.sign.keyPair.fromSeed(
6
- Buffer.from(privateKey, 'hex').slice(0, 32)
7
- )
8
-
9
- return {
10
- secretKey: Buffer.from(secretKey, 'hex'), // secretKey
11
- publicKey: Buffer.from(publicKey, 'hex'),
12
- }
13
- }
14
-
15
- export function getPublicKey(privateKey: string | Buffer): Buffer {
16
- return getKeyPairFromPrivateKey(privateKey).publicKey
17
- }
18
-
19
- export function sign(data: Buffer, privateKey: string | Buffer): Buffer {
20
- return Buffer.from(
21
- nacl.sign.detached(data, getKeyPairFromPrivateKey(Buffer.from(privateKey, 'hex')).secretKey),
22
- 'hex'
23
- )
24
- }
25
-
26
- export function verifySignature(
27
- data: Buffer,
28
- signature: Buffer,
29
- publicKey: string | Buffer
30
- ): boolean {
31
- return nacl.sign.detached.verify(data, signature, Buffer.from(publicKey, 'hex'))
32
- }
package/src/tokens.js DELETED
@@ -1,19 +0,0 @@
1
- // adapted from https://github.com/project-serum/spl-token-wallet/blob/master/src/utils/tokens/names.js
2
-
3
- const TOKENS = [
4
- {
5
- mintAddress: 'SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt',
6
- tokenName: 'serum',
7
- tokenProperName: 'Serum',
8
- tokenSymbol: 'SRM',
9
- },
10
- {
11
- mintAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
12
- tokenName: 'usdcoin_solana',
13
- tokenProperName: 'USD Coin Solana',
14
- tokenSymbol: 'USDCSOL',
15
- },
16
- // ....
17
- ]
18
-
19
- export default TOKENS