@exodus/solana-lib 1.2.29 → 1.3.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/solana-lib",
3
- "version": "1.2.29",
3
+ "version": "1.3.1",
4
4
  "description": "Exodus internal Solana low-level library",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -25,5 +25,5 @@
25
25
  "lodash": "^4.17.11",
26
26
  "tweetnacl": "^1.0.3"
27
27
  },
28
- "gitHead": "69134d5324df0b3977a84b39e1098876a5ebffe7"
28
+ "gitHead": "49f3f78ac41acaf405e2849cccb2f9ecd0060424"
29
29
  }
package/src/constants.js CHANGED
@@ -14,3 +14,7 @@ export const MAGIC_EDEN_ESCROW_PROGRAM_ID = new PublicKey(
14
14
  )
15
15
 
16
16
  export const SEED = 'stake:0'
17
+
18
+ export const LAMPORTS_PER_SOL = 1000000000
19
+
20
+ export const SOL_DECIMAL = Math.log10(LAMPORTS_PER_SOL)
@@ -3,71 +3,71 @@
3
3
  import bs58 from 'bs58'
4
4
  import { BinaryReader, BinaryWriter } from 'borsh'
5
5
 
6
- BinaryReader.prototype.readPubkeyAsString = function () {
6
+ BinaryReader.prototype.readPubkeyAsString = function() {
7
7
  const reader = this
8
8
  const array = reader.readFixedArray(32)
9
9
  return bs58.encode(array)
10
10
  }
11
11
 
12
- BinaryWriter.prototype.writePubkeyAsString = function (value) {
12
+ BinaryWriter.prototype.writePubkeyAsString = function(value) {
13
13
  const writer = this
14
14
  writer.writeFixedArray(bs58.decode(value))
15
15
  }
16
16
 
17
17
  class Data {
18
18
  constructor(args) {
19
- this.name = args.name;
20
- this.symbol = args.symbol;
21
- this.uri = args.uri;
22
- this.sellerFeeBasisPoints = args.sellerFeeBasisPoints;
23
- this.creators = args.creators;
19
+ this.name = args.name
20
+ this.symbol = args.symbol
21
+ this.uri = args.uri
22
+ this.sellerFeeBasisPoints = args.sellerFeeBasisPoints
23
+ this.creators = args.creators
24
24
  }
25
25
  }
26
26
 
27
27
  class Creator {
28
- constructor(args) {
29
- this.address = args.address;
30
- this.verified = args.verified;
31
- this.share = args.share;
32
- }
28
+ constructor(args) {
29
+ this.address = args.address
30
+ this.verified = args.verified
31
+ this.share = args.share
32
+ }
33
33
  }
34
34
 
35
35
  class Metadata {
36
36
  constructor(args) {
37
37
  this.key = '' // MetadataKey.MetadataV1;
38
- this.updateAuthority = args.updateAuthority;
39
- this.mint = args.mint;
40
- this.data = args.data;
41
- this.primarySaleHappened = args.primarySaleHappened;
42
- this.isMutable = args.isMutable;
43
- this.editionNonce = args.editionNonce || null;
38
+ this.updateAuthority = args.updateAuthority
39
+ this.mint = args.mint
40
+ this.data = args.data
41
+ this.primarySaleHappened = args.primarySaleHappened
42
+ this.isMutable = args.isMutable
43
+ this.editionNonce = args.editionNonce || null
44
44
  }
45
45
  }
46
46
 
47
47
  const METADATA_SCHEMA = new Map([
48
48
  [
49
- Data,
50
- {
51
- kind: 'struct',
52
- fields: [
53
- ['name', 'string'],
54
- ['symbol', 'string'],
55
- ['uri', 'string'],
56
- ['sellerFeeBasisPoints', 'u16'],
57
- ['creators', { kind: 'option', type: [Creator] }],
58
- ],
59
- },
49
+ Data,
50
+ {
51
+ kind: 'struct',
52
+ fields: [
53
+ ['name', 'string'],
54
+ ['symbol', 'string'],
55
+ ['uri', 'string'],
56
+ ['sellerFeeBasisPoints', 'u16'],
57
+ ['creators', { kind: 'option', type: [Creator] }],
58
+ ],
59
+ },
60
60
  ],
61
61
  [
62
- Creator,
63
- {
64
- kind: 'struct',
65
- fields: [
66
- ['address', 'pubkeyAsString'],
67
- ['verified', 'u8'],
68
- ['share', 'u8'],
69
- ],
70
- },
62
+ Creator,
63
+ {
64
+ kind: 'struct',
65
+ fields: [
66
+ ['address', 'pubkeyAsString'],
67
+ ['verified', 'u8'],
68
+ ['share', 'u8'],
69
+ ],
70
+ },
71
71
  ],
72
72
  [
73
73
  Metadata,
@@ -84,10 +84,9 @@ const METADATA_SCHEMA = new Map([
84
84
  ],
85
85
  },
86
86
  ],
87
- ]);
88
-
87
+ ])
89
88
 
90
89
  module.exports = {
91
90
  METADATA_SCHEMA,
92
- Metadata
91
+ Metadata,
93
92
  }
@@ -43,6 +43,20 @@ export class U64 extends BN {
43
43
 
44
44
  const u64 = U64 // alias
45
45
 
46
+ /**
47
+ * Layout for a public key
48
+ */
49
+ const publicKey = (property = 'publicKey') => {
50
+ return BufferLayout.blob(32, property)
51
+ }
52
+
53
+ /**
54
+ * Layout for a 64bit unsigned value
55
+ */
56
+ const uint64 = (property = 'uint64') => {
57
+ return BufferLayout.blob(8, property)
58
+ }
59
+
46
60
  /**
47
61
  * An ERC20-like Token
48
62
  */
@@ -105,4 +119,20 @@ export class Token {
105
119
  data,
106
120
  })
107
121
  }
122
+
123
+ static decode(data: string) {
124
+ return BufferLayout.struct([
125
+ publicKey('mint'),
126
+ publicKey('owner'),
127
+ uint64('amount'),
128
+ BufferLayout.u32('delegateOption'),
129
+ publicKey('delegate'),
130
+ BufferLayout.u8('state'),
131
+ BufferLayout.u32('isNativeOption'),
132
+ uint64('isNative'),
133
+ uint64('delegatedAmount'),
134
+ BufferLayout.u32('closeAuthorityOption'),
135
+ publicKey('closeAuthority'),
136
+ ]).decode(data)
137
+ }
108
138
  }
package/src/index.js CHANGED
@@ -4,6 +4,10 @@ export * from './constants'
4
4
  export * from './encode'
5
5
  export * from './keypair'
6
6
  export * from './tx'
7
- export { StakeInstruction, PublicKey, Transaction as SolanaWeb3Transaction, Message as SolanaWeb3Message } from './vendor'
8
- export { default as tokens } from './tokens'
7
+ export {
8
+ StakeInstruction,
9
+ PublicKey,
10
+ Transaction as SolanaWeb3Transaction,
11
+ Message as SolanaWeb3Message,
12
+ } from './vendor'
9
13
  export { default as Transaction } from './transaction'
@@ -22,7 +22,6 @@ import {
22
22
  } from './vendor'
23
23
  import { MagicEdenEscrowProgram } from './magiceden/escrow-program'
24
24
  import { SEED, STAKE_PROGRAM_ID } from './constants'
25
- import TOKENS from './tokens'
26
25
 
27
26
  class Tx {
28
27
  constructor({
@@ -33,7 +32,6 @@ class Tx {
33
32
  // fee, // (Fee per Signature: 5000 lamports)
34
33
  // Tokens related:
35
34
  // pass either name or mintAddress, if both, mintAddress has priority
36
- tokenName,
37
35
  tokenMintAddress,
38
36
  destinationAddressType,
39
37
  isAssociatedTokenAccountActive, // true when recipient balance !== 0
@@ -44,7 +42,7 @@ class Tx {
44
42
  assert(amount, 'amount is required')
45
43
  assert(typeof amount === 'number', 'amount must be a number')
46
44
  assert(recentBlockhash, 'recentBlockhash is required')
47
- if (tokenName || tokenMintAddress) {
45
+ if (tokenMintAddress) {
48
46
  assert(
49
47
  typeof destinationAddressType !== 'undefined',
50
48
  'destinationAddressType is required when sending tokens'
@@ -56,12 +54,6 @@ class Tx {
56
54
  assert(Array.isArray(fromTokenAddresses), 'fromTokenAddresses Array is required')
57
55
  }
58
56
 
59
- if (tokenName && !tokenMintAddress) {
60
- const token = TOKENS.find(({ name }) => name === tokenName)
61
- assert(token, `token with tokenName ${tokenName} not found in tokens list`)
62
- tokenMintAddress = token.mintAddress
63
- }
64
-
65
57
  this.txObj = {
66
58
  from,
67
59
  to,
@@ -8,7 +8,6 @@ export function createUnsignedTx({
8
8
  fee,
9
9
  recentBlockhash,
10
10
  // Tokens related:
11
- tokenName,
12
11
  tokenMintAddress,
13
12
  destinationAddressType,
14
13
  isAssociatedTokenAccountActive, // true when recipient balance !== 0
@@ -40,7 +39,6 @@ export function createUnsignedTx({
40
39
  fee: fee.toBase().toNumber(),
41
40
  recentBlockhash,
42
41
  // Tokens related:
43
- tokenName,
44
42
  tokenMintAddress,
45
43
  destinationAddressType,
46
44
  isAssociatedTokenAccountActive,
package/src/tx/index.js CHANGED
@@ -2,3 +2,4 @@ export * from './sign-unsigned-tx'
2
2
  export * from './parse-unsigned-tx'
3
3
  export * from './create-unsigned-tx'
4
4
  export * from './create-and-sign-tx'
5
+ export * from './simulate-and-sign-tx'
@@ -7,7 +7,6 @@ export function parseUnsignedTx(unsignedTx: UnsignedTransaction): ParsedTransact
7
7
  from,
8
8
  to,
9
9
  recentBlockhash,
10
- tokenName,
11
10
  tokenMintAddress,
12
11
  destinationAddressType,
13
12
  isAssociatedTokenAccountActive,
@@ -40,7 +39,6 @@ export function parseUnsignedTx(unsignedTx: UnsignedTransaction): ParsedTransact
40
39
  fee,
41
40
  recentBlockhash,
42
41
  // token related
43
- tokenName,
44
42
  tokenMintAddress,
45
43
  destinationAddressType,
46
44
  isAssociatedTokenAccountActive,
@@ -12,7 +12,6 @@ export function signUnsignedTx(
12
12
  amount: unitAmount,
13
13
  recentBlockhash,
14
14
  // tokens related
15
- tokenName,
16
15
  tokenMintAddress,
17
16
  destinationAddressType,
18
17
  isAssociatedTokenAccountActive,
@@ -109,7 +108,6 @@ export function signUnsignedTx(
109
108
  to,
110
109
  amount,
111
110
  recentBlockhash,
112
- tokenName,
113
111
  tokenMintAddress,
114
112
  destinationAddressType,
115
113
  isAssociatedTokenAccountActive,
@@ -0,0 +1,77 @@
1
+ import { Token, U64 } from '../helpers/spl-token'
2
+ import { PublicKey } from '../vendor/'
3
+
4
+ export function computeBalance(futureAccountBalance: string, currentAccountBalance: string) {
5
+ return new U64(futureAccountBalance).sub(new U64(currentAccountBalance))
6
+ }
7
+
8
+ export function getTransactionSimulationParams(transaction) {
9
+ const config = {
10
+ encoding: 'base64',
11
+ commitment: 'confirmed',
12
+ }
13
+
14
+ const accountAddresses = transaction
15
+ .compileMessage()
16
+ .accountKeys.map((account) => account.toString())
17
+ config['accounts'] = {
18
+ encoding: 'base64',
19
+ addresses: accountAddresses,
20
+ }
21
+
22
+ return {
23
+ config,
24
+ accountAddresses,
25
+ }
26
+ }
27
+
28
+ const isSolAccount = (account) => account === '1111111111111111'
29
+
30
+ export function filterAccountsByOwner(futureAccountsState, accountAddresses, publicKey) {
31
+ const solAccounts = []
32
+ const tokenAccounts = []
33
+
34
+ // Shouldn't happen
35
+ if (futureAccountsState.length !== accountAddresses.length) {
36
+ throw Error('Simulation returning wrong account length')
37
+ }
38
+
39
+ futureAccountsState.forEach((futureAccount, index) => {
40
+ try {
41
+ const accountAddress = accountAddresses[index]
42
+
43
+ // Check if it's SOL account (not token)
44
+ if (isSolAccount(futureAccount.owner.toString())) {
45
+ if (accountAddress.toString() === publicKey.toString()) {
46
+ solAccounts.push({
47
+ amount: futureAccount.lamports,
48
+ address: publicKey,
49
+ })
50
+ }
51
+ return
52
+ }
53
+
54
+ const data = Buffer.from(futureAccount.data[0], 'base64')
55
+ const token = Token.decode(data)
56
+ const owner = new PublicKey(token.owner).toString()
57
+ const amount = U64.fromBuffer(token.amount)
58
+
59
+ // Get tokens by owner using the public key
60
+ if (owner === publicKey.toString()) {
61
+ tokenAccounts.push({
62
+ amount,
63
+ mint: new PublicKey(token.mint).toString(),
64
+ owner: owner,
65
+ address: accountAddress.toString(),
66
+ })
67
+ }
68
+ } catch (error) {
69
+ console.warn(error)
70
+ }
71
+ })
72
+
73
+ return {
74
+ solAccounts,
75
+ tokenAccounts,
76
+ }
77
+ }
package/src/tokens.js DELETED
@@ -1,12 +0,0 @@
1
- import assets from '@exodus/assets'
2
-
3
- // tokens info: https://github.com/project-serum/spl-token-wallet/blob/master/src/utils/tokens/names.js
4
-
5
- const tokens = Object.values(assets)
6
- .filter((asset) => asset.assetType === 'SOLANA_TOKEN')
7
- .map((token) => ({
8
- ...token,
9
- tokenName: token.name, // alias
10
- }))
11
-
12
- export default tokens