@exodus/solana-api 3.6.1 → 3.7.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/CHANGELOG.md ADDED
@@ -0,0 +1,178 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ ## [3.7.0](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.6.2...@exodus/solana-api@3.7.0) (2024-06-13)
7
+
8
+
9
+ ### Features
10
+
11
+ * use ME API for SOL fungible assets ([#2490](https://github.com/ExodusMovement/assets/issues/2490)) ([8234222](https://github.com/ExodusMovement/assets/commit/82342222f57949da4d7128f7f92baf6a0bc1781e))
12
+
13
+
14
+
15
+ ## [3.6.2](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.6.1...@exodus/solana-api@3.6.2) (2024-06-11)
16
+
17
+ **Note:** Version bump only for package @exodus/solana-api
18
+
19
+
20
+
21
+
22
+
23
+ ## [3.6.1](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.6.0...@exodus/solana-api@3.6.1) (2024-06-06)
24
+
25
+
26
+ ### Bug Fixes
27
+
28
+ * set solana pool address ([#2494](https://github.com/ExodusMovement/assets/issues/2494)) ([1307021](https://github.com/ExodusMovement/assets/commit/13070218d33476ea1c9603dc01cb1852dd89d701))
29
+
30
+
31
+
32
+ ## [3.6.0](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.5.0...@exodus/solana-api@3.6.0) (2024-05-31)
33
+
34
+
35
+ ### Features
36
+
37
+ * add SOL staking provider client ([#2420](https://github.com/ExodusMovement/assets/issues/2420)) ([a39413d](https://github.com/ExodusMovement/assets/commit/a39413db095f12f9f8dfb757a56052561d399616))
38
+
39
+
40
+
41
+ ## [3.5.0](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.4.2...@exodus/solana-api@3.5.0) (2024-05-29)
42
+
43
+
44
+ ### Features
45
+
46
+ * **solana:** add getFeeForMessage to Solana API ([#2203](https://github.com/ExodusMovement/assets/issues/2203)) ([26bf824](https://github.com/ExodusMovement/assets/commit/26bf82496932c7d1f183afaeb75e224f831571e2))
47
+
48
+
49
+
50
+ ## [3.4.2](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.4.1...@exodus/solana-api@3.4.2) (2024-05-28)
51
+
52
+
53
+ ### Bug Fixes
54
+
55
+ * add recommended option to getPriorityFeeEstimate rpc ([#2402](https://github.com/ExodusMovement/assets/issues/2402)) ([d010996](https://github.com/ExodusMovement/assets/commit/d010996a05833d0517559a6697af02fba7fe6b2b))
56
+
57
+
58
+
59
+ ## [3.4.1](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.4.0...@exodus/solana-api@3.4.1) (2024-04-22)
60
+
61
+ **Note:** Version bump only for package @exodus/solana-api
62
+
63
+
64
+
65
+
66
+
67
+ ## [3.4.0](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.3.2...@exodus/solana-api@3.4.0) (2024-04-20)
68
+
69
+
70
+ ### Features
71
+
72
+ * add compute budget instruction ([#2006](https://github.com/ExodusMovement/assets/issues/2006)) ([f1479ac](https://github.com/ExodusMovement/assets/commit/f1479aca619370da573f442ef4526e6d21db14d2))
73
+
74
+
75
+
76
+ ## [3.3.2](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.3.1...@exodus/solana-api@3.3.2) (2024-04-17)
77
+
78
+ ### Bug Fixes
79
+
80
+ * support solana spl -> sol dex txs ([#2045](https://github.com/ExodusMovement/assets/issues/2045)) ([d48bd85](https://github.com/ExodusMovement/assets/commit/d48bd85d2b52e1daaa92a1c00ce6c9d6309ebbf7))
81
+
82
+
83
+
84
+ ## [3.3.1](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.3.0...@exodus/solana-api@3.3.1) (2024-04-12)
85
+
86
+
87
+ ### Bug Fixes
88
+
89
+ * add fetch polyfill with exodus user-agent ([#1983](https://github.com/ExodusMovement/assets/issues/1983)) ([4dc0e23](https://github.com/ExodusMovement/assets/commit/4dc0e23f397a9bc257ccb5589077d80c29172abe))
90
+ * **solana:** send transaction changes ([#2027](https://github.com/ExodusMovement/assets/issues/2027)) ([0047303](https://github.com/ExodusMovement/assets/commit/0047303b72e76620617a119f845bb4f26074912f))
91
+
92
+
93
+
94
+ ## [3.3.0](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.2.0...@exodus/solana-api@3.3.0) (2024-04-04)
95
+
96
+
97
+ ### Features
98
+
99
+ * implement helius priority fee ([#1799](https://github.com/ExodusMovement/assets/issues/1799)) ([e681ee7](https://github.com/ExodusMovement/assets/commit/e681ee7f52526bc8a77ab9917d57fb5c2fca2fd4))
100
+
101
+
102
+
103
+ ## [3.2.0](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.1.0...@exodus/solana-api@3.2.0) (2024-03-29)
104
+
105
+
106
+ ### Features
107
+
108
+ * solana new balances ([#1913](https://github.com/ExodusMovement/assets/issues/1913)) ([f83c5f7](https://github.com/ExodusMovement/assets/commit/f83c5f7b3e450df9fcd6790a6b40a6797e42dc2e))
109
+
110
+
111
+
112
+ ## [3.1.0](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.0.0...@exodus/solana-api@3.1.0) (2024-03-27)
113
+
114
+
115
+ ### Features
116
+
117
+ * add new Solana token 2022 program ([#1808](https://github.com/ExodusMovement/assets/issues/1808)) ([90747bc](https://github.com/ExodusMovement/assets/commit/90747bc97fba0e629a1eaba5878dd06f834b0d72))
118
+
119
+
120
+ ### Bug Fixes
121
+
122
+ * support token-2022 program for metaplex transfer ([#1894](https://github.com/ExodusMovement/assets/issues/1894)) ([31f712a](https://github.com/ExodusMovement/assets/commit/31f712a8fda681969b1c3dbe6f4c5e3d250f3062))
123
+
124
+
125
+
126
+ ## [3.0.0](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@2.5.34...@exodus/solana-api@3.0.0) (2024-03-21)
127
+
128
+
129
+ ### ⚠ BREAKING CHANGES
130
+
131
+ * expose account state factory function (#1832)
132
+
133
+ ### Features
134
+
135
+ * **solana-api:** pass feeData to createUnsignedTx ([#1815](https://github.com/ExodusMovement/assets/issues/1815)) ([3c6fe2a](https://github.com/ExodusMovement/assets/commit/3c6fe2a529b362025482c858cf0c0a102291b62e))
136
+
137
+
138
+ ### Code Refactoring
139
+
140
+ * expose account state factory function ([#1832](https://github.com/ExodusMovement/assets/issues/1832)) ([1879d7b](https://github.com/ExodusMovement/assets/commit/1879d7ba060e5c7f08316711df5b94448e7bcea6))
141
+
142
+
143
+
144
+ ## [2.5.34](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@2.5.33...@exodus/solana-api@2.5.34) (2024-03-18)
145
+
146
+
147
+ ### Bug Fixes
148
+
149
+ * pass in txsLimit to solana monitor ([#1792](https://github.com/ExodusMovement/assets/issues/1792)) ([7283048](https://github.com/ExodusMovement/assets/commit/7283048c56b239a690064d14ff9b4d0228c078a9))
150
+
151
+
152
+
153
+
154
+
155
+ ## [2.5.33](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@2.5.32...@exodus/solana-api@2.5.33) (2024-03-18)
156
+
157
+
158
+ ### Bug Fixes
159
+
160
+ * prefer on-chain data over account state calculation ([#1781](https://github.com/ExodusMovement/assets/issues/1781)) ([aa5cbcf](https://github.com/ExodusMovement/assets/commit/aa5cbcf81c3e5d0ee29a8650d74ab928e1317724))
161
+
162
+
163
+
164
+
165
+
166
+ ## [2.5.32](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@2.5.30...@exodus/solana-api@2.5.32) (2024-03-16)
167
+
168
+
169
+ ### Features
170
+
171
+ * limit SOL txs to latest 100 ([#1688](https://github.com/ExodusMovement/assets/issues/1688)) ([6b24ac5](https://github.com/ExodusMovement/assets/commit/6b24ac57c1e3d0f2eccb1efdaad9b9a1759d3a7c))
172
+ * solana monitor history refactor to use fewer transaction rpc calls ([#1559](https://github.com/ExodusMovement/assets/issues/1559)) ([8933aa6](https://github.com/ExodusMovement/assets/commit/8933aa61d712faf9665de87bdc1a1c5cabd2d403))
173
+ * **solana:** migrate some implementations and remove `@exodus/solana-spl-tokan` usage. ([#1669](https://github.com/ExodusMovement/assets/issues/1669)) ([ee75e1f](https://github.com/ExodusMovement/assets/commit/ee75e1fbf5c276aafc91260dee9ad6e44e5c8b8b))
174
+
175
+
176
+ ### Bug Fixes
177
+
178
+ * solana set stake amount when in tx on tx-send ([#1752](https://github.com/ExodusMovement/assets/issues/1752)) ([7c09616](https://github.com/ExodusMovement/assets/commit/7c0961624df39bbb57a5c3bce395f8f31f3be141))
package/package.json CHANGED
@@ -1,22 +1,23 @@
1
1
  {
2
2
  "name": "@exodus/solana-api",
3
- "version": "3.6.1",
3
+ "version": "3.7.0",
4
4
  "description": "Exodus internal Solana asset API wrapper",
5
5
  "main": "src/index.js",
6
6
  "files": [
7
7
  "src",
8
- "!src/**/__tests__",
8
+ "CHANGELOG.md",
9
+ "package.json",
9
10
  "README.md",
10
- "package.json"
11
+ "!src/**/__tests__"
11
12
  ],
12
- "author": "Exodus",
13
+ "author": "Exodus Movement, Inc.",
13
14
  "license": "ISC",
14
15
  "publishConfig": {
15
16
  "access": "restricted"
16
17
  },
17
18
  "scripts": {
18
19
  "test": "run -T jest",
19
- "lint": "run -T eslint ./src",
20
+ "lint": "run -T eslint .",
20
21
  "lint:fix": "yarn lint --fix"
21
22
  },
22
23
  "dependencies": {
@@ -38,12 +39,20 @@
38
39
  "make-concurrent": "^4.0.0",
39
40
  "minimalistic-assert": "^1.0.1",
40
41
  "ms": "^2.1.3",
41
- "url-join": "4.0.0",
42
+ "url-join": "^4.0.0",
42
43
  "wretch": "^1.5.2"
43
44
  },
44
45
  "devDependencies": {
45
46
  "@exodus/assets-testing": "^1.0.0",
46
47
  "@solana/web3.js": "^1.91.8"
47
48
  },
48
- "gitHead": "9d24eb58422692fc1acdcb834061d02b2632801d"
49
+ "gitHead": "0703f508ef7b1a34bc99f910e6220989382abc00",
50
+ "bugs": {
51
+ "url": "https://github.com/ExodusMovement/assets/issues?q=is%3Aissue+is%3Aopen+label%3Asolana-api"
52
+ },
53
+ "homepage": "https://github.com/ExodusMovement/assets/tree/master/solana/solana-api",
54
+ "repository": {
55
+ "type": "git",
56
+ "url": "git+https://github.com/ExodusMovement/assets.git"
57
+ }
49
58
  }
package/src/api.js CHANGED
@@ -2,17 +2,17 @@ import BN from 'bn.js'
2
2
  import createApi from '@exodus/asset-json-rpc'
3
3
  import { retry } from '@exodus/simple-retry'
4
4
  import {
5
- getMetadataAccount,
5
+ buildRawTransaction,
6
+ computeBalance,
6
7
  deserializeMetaplexMetadata,
7
- getTransactionSimulationParams,
8
8
  filterAccountsByOwner,
9
- SYSTEM_PROGRAM_ID,
9
+ getMetadataAccount,
10
+ getTransactionSimulationParams,
11
+ SOL_DECIMAL,
10
12
  STAKE_PROGRAM_ID,
11
- TOKEN_PROGRAM_ID,
13
+ SYSTEM_PROGRAM_ID,
12
14
  TOKEN_2022_PROGRAM_ID,
13
- SOL_DECIMAL,
14
- computeBalance,
15
- buildRawTransaction,
15
+ TOKEN_PROGRAM_ID,
16
16
  } from '@exodus/solana-lib'
17
17
  import assert from 'assert'
18
18
  import lodash from 'lodash'
@@ -37,6 +37,11 @@ export class Api {
37
37
  this.tokensToSkip = {}
38
38
  this.txsLimit = txsLimit
39
39
  this.connections = {}
40
+ this.getSupply = lodash.memoize(async (mintAddress) => {
41
+ // cached getSupply
42
+ const result = await this.rpcCall('getTokenSupply', [mintAddress])
43
+ return lodash.get(result, 'value.amount')
44
+ })
40
45
  }
41
46
 
42
47
  setServer(rpcUrl) {
@@ -620,11 +625,6 @@ export class Api {
620
625
  }
621
626
  }
622
627
 
623
- async getSupply(mintAddress) {
624
- const result = await this.rpcCall('getTokenSupply', [mintAddress])
625
- return lodash.get(result, 'value.amount')
626
- }
627
-
628
628
  async getWalletTokensList({ tokenAccounts }) {
629
629
  const tokensMint = []
630
630
  for (const account of tokenAccounts) {
@@ -635,10 +635,12 @@ export class Api {
635
635
  // skip 0 balance
636
636
  if (account.balance === '0') continue
637
637
  // skip NFT
638
- const supply = await this.getSupply(mint)
639
- if (supply === '1') {
640
- this.tokensToSkip[mint] = true
641
- continue
638
+ if (!this.tokens.has(mint)) {
639
+ const supply = await this.getSupply(mint)
640
+ if (supply === '1') {
641
+ this.tokensToSkip[mint] = true
642
+ continue
643
+ }
642
644
  }
643
645
 
644
646
  // OK
@@ -0,0 +1,18 @@
1
+ import wretch from 'wretch'
2
+ import urljoin from 'url-join'
3
+
4
+ const FLAGR_URL = 'https://flagr-w.magiceden.io/api/v1/evaluation'
5
+
6
+ const fetchFlagrEvaluation = async (wallet, flagKey) => {
7
+ const url = urljoin(FLAGR_URL)
8
+ const entityContext = { wallet }
9
+
10
+ try {
11
+ return await wretch(url).post({ entityContext, flagKey }).json()
12
+ } catch (error) {
13
+ console.error('Error fetching flagr:', error)
14
+ throw error
15
+ }
16
+ }
17
+
18
+ export default fetchFlagrEvaluation
@@ -0,0 +1,135 @@
1
+ import { SolanaMonitor } from './solana-monitor'
2
+ import wretch from 'wretch'
3
+ import urljoin from 'url-join'
4
+ import fetchFlagrEvaluation from './me-flagr'
5
+
6
+ const FLAGR_KEY = 'sol-balance-api'
7
+ const SOL_NATIVE = '11111111111111111111111111111111'
8
+
9
+ export class MeSolanaMonitor extends SolanaMonitor {
10
+ #extraHeaders
11
+
12
+ constructor(args) {
13
+ super(args)
14
+ this.useMeMonitor = false
15
+ this.#extraHeaders = args.extraHeaders
16
+ }
17
+
18
+ async startListener({ walletAccount }) {
19
+ const address = await this.aci.getReceiveAddress({
20
+ assetName: this.asset.name,
21
+ walletAccount,
22
+ useCache: true,
23
+ })
24
+ await this.initFlagr(address)
25
+ return super.startListener({ walletAccount })
26
+ }
27
+
28
+ request(path, contentType = 'application/json') {
29
+ return wretch(urljoin('https://api-mainnet.magiceden.io', path)).headers({
30
+ 'Content-Type': contentType,
31
+ ...this.#extraHeaders,
32
+ })
33
+ }
34
+
35
+ async initFlagr(address) {
36
+ // If one of the user's SOL addresses is whitelisted, use the ME API
37
+ if (this.useMeMonitor) return
38
+ try {
39
+ const response = await fetchFlagrEvaluation(address, FLAGR_KEY)
40
+ if (response.variantKey === 'on') {
41
+ this.useMeMonitor = true
42
+ }
43
+ } catch (error) {
44
+ console.error('Failed to fetch useMeMonitor config:', error)
45
+ }
46
+ }
47
+
48
+ getTokens() {
49
+ return this.api.tokens
50
+ }
51
+
52
+ isStakingEnabled() {
53
+ return this.staking.enabled
54
+ }
55
+
56
+ async getTokenAccounts({ address }) {
57
+ if (!this.useMeMonitor) {
58
+ return super.getTokenAccounts({ address })
59
+ }
60
+
61
+ const tokens = this.getTokens()
62
+ const body = [
63
+ {
64
+ address,
65
+ chain: 'solana',
66
+ },
67
+ ]
68
+
69
+ const { balances } = await this.request('v1/wallet/balances/fungible').post(body).json()
70
+
71
+ return balances
72
+ .filter((balance) => balance.asset.mintAddress !== SOL_NATIVE)
73
+ .map((balance) => {
74
+ const asset = balance.asset
75
+ const mintAddress = asset.mintAddress
76
+ const token = tokens.get(mintAddress) || {
77
+ // name here is the exodus unique identifier not the display name
78
+ name: 'unknown',
79
+ ticker: asset.symbol,
80
+ decimals: balance.decimals,
81
+ }
82
+
83
+ return {
84
+ tokenAccountAddress: asset.tokenAccount,
85
+ owner: balance.owner,
86
+ tokenName: token.name,
87
+ ticker: token.ticker,
88
+ balance: balance.balance.rawBalance,
89
+ mintAddress,
90
+ tokenProgram: asset.tokenProgram,
91
+ decimals: token.decimals,
92
+ feeBasisPoints: asset.feeBasisPoints ?? 0,
93
+ maximumFee: asset.maximumFee ?? 0,
94
+ }
95
+ })
96
+ }
97
+
98
+ async getAccount({ address, staking, tokenAccounts }) {
99
+ if (!this.useMeMonitor) {
100
+ return super.getAccount({ address })
101
+ }
102
+
103
+ const tokens = this.getTokens()
104
+ const body = [
105
+ {
106
+ address,
107
+ chain: 'solana',
108
+ },
109
+ ]
110
+
111
+ const { balances } = await this.request('v1/wallet/balances/fungible').post(body).json()
112
+
113
+ const result = {
114
+ balance: null,
115
+ tokenBalances: {},
116
+ }
117
+
118
+ balances.forEach((balanceData) => {
119
+ const { asset: responseAsset, balance } = balanceData
120
+ const mintAddress = responseAsset.mintAddress
121
+
122
+ if (mintAddress === SOL_NATIVE) {
123
+ // SOL balance
124
+ result.balance = this.asset.currency.baseUnit(balance.rawBalance)
125
+ } else if (tokens.has(mintAddress)) {
126
+ // Fungible token balances
127
+ const token = tokens.get(mintAddress)
128
+ const tokenKey = token.name
129
+ result.tokenBalances[tokenKey] = token.currency.baseUnit(balance.rawBalance)
130
+ }
131
+ })
132
+
133
+ return result
134
+ }
135
+ }
@@ -54,6 +54,7 @@ export class SolanaMonitor extends BaseMonitor {
54
54
  walletAccount,
55
55
  useCache: true,
56
56
  })
57
+
57
58
  return this.api.watchAddress({
58
59
  address,
59
60
  onMessage: (json) => {
@@ -133,6 +134,14 @@ export class SolanaMonitor extends BaseMonitor {
133
134
  return clearedLogItems
134
135
  }
135
136
 
137
+ async getTokenAccounts({ address }) {
138
+ return this.api.getTokenAccountsByOwner(address)
139
+ }
140
+
141
+ isStakingEnabled() {
142
+ return true
143
+ }
144
+
136
145
  async tick({ walletAccount, refresh }) {
137
146
  // Check for new wallet account
138
147
  await this.initWalletAccount({ walletAccount })
@@ -146,11 +155,12 @@ export class SolanaMonitor extends BaseMonitor {
146
155
  const stakingAddresses = await this.getStakingAddressesFromTxLog({ assetName, walletAccount })
147
156
 
148
157
  const fetchStakingInfo = this.tickCount[walletAccount] % this.ticksBetweenStakeFetches === 0
149
- const staking = fetchStakingInfo
150
- ? await this.getStakingInfo({ address, stakingAddresses })
151
- : { ...accountState.mem, staking: this.staking }
158
+ const staking =
159
+ this.isStakingEnabled() && fetchStakingInfo
160
+ ? await this.getStakingInfo({ address, stakingAddresses })
161
+ : { ...accountState.mem, staking: this.staking }
152
162
 
153
- const tokenAccounts = await this.api.getTokenAccountsByOwner(address)
163
+ const tokenAccounts = await this.getTokenAccounts({ address })
154
164
  const account = await this.getAccount({ address, staking, tokenAccounts })
155
165
 
156
166
  const balanceChanged = this.#balanceChanged({ account: accountState, newAccount: account })