@exodus/solana-api 1.3.3 → 1.4.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.
Files changed (2) hide show
  1. package/package.json +3 -3
  2. package/src/index.js +101 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/solana-api",
3
- "version": "1.3.3",
3
+ "version": "1.4.0",
4
4
  "description": "Exodus internal Solana asset API wrapper",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "dependencies": {
16
16
  "@exodus/asset-json-rpc": "^1.0.0",
17
- "@exodus/solana-lib": "^1.2.29",
17
+ "@exodus/solana-lib": "^1.3.0",
18
18
  "lodash": "^4.17.11",
19
19
  "url-join": "4.0.0",
20
20
  "wretch": "^1.5.2"
@@ -22,5 +22,5 @@
22
22
  "devDependencies": {
23
23
  "node-fetch": "~1.6.3"
24
24
  },
25
- "gitHead": "69134d5324df0b3977a84b39e1098876a5ebffe7"
25
+ "gitHead": "158aae6b4aeb871b1566b2500456a5f475ef9d5f"
26
26
  }
package/src/index.js CHANGED
@@ -3,10 +3,14 @@ import createApi from '@exodus/asset-json-rpc'
3
3
  import {
4
4
  getMetadataAccount,
5
5
  deserializeMetaplexMetadata,
6
+ getTransactionSimulationParams,
7
+ filterAccountsByOwner,
6
8
  tokens,
7
9
  SYSTEM_PROGRAM_ID,
8
10
  STAKE_PROGRAM_ID,
9
11
  TOKEN_PROGRAM_ID,
12
+ SOL_DECIMAL,
13
+ computeBalance,
10
14
  } from '@exodus/solana-lib'
11
15
  import assert from 'assert'
12
16
  import lodash from 'lodash'
@@ -409,6 +413,18 @@ class Api {
409
413
  }
410
414
  }
411
415
 
416
+ // Returns account balance of a SPL Token account.
417
+ async getTokenBalance(tokenAddress: string) {
418
+ const {
419
+ value: { amount },
420
+ } = await this.api.post({
421
+ method: 'getTokenAccountBalance',
422
+ params: [tokenAddress],
423
+ })
424
+
425
+ return amount
426
+ }
427
+
412
428
  async getAccountInfo(address: string) {
413
429
  const { value } = await this.api.post({
414
430
  method: 'getAccountInfo',
@@ -560,6 +576,91 @@ class Api {
560
576
  console.log(`tx ${JSON.stringify(result)} sent!`)
561
577
  return result || null
562
578
  }
579
+
580
+ simulateTransaction = async (transaction, options) => {
581
+ const {
582
+ value: { accounts },
583
+ } = await this.api.post({
584
+ method: 'simulateTransaction',
585
+ params: [transaction.serialize({ verifySignatures: false }).toString('base64'), options],
586
+ })
587
+
588
+ return accounts
589
+ }
590
+
591
+ resolveSimulationSideEffects = async (solAccounts, tokenAccounts) => {
592
+ const willReceive = []
593
+ const willSend = []
594
+
595
+ const resolveSols = solAccounts.map(async (account) => {
596
+ const currentAmount = await this.getBalance(account.address)
597
+ const balance = computeBalance(account.amount, currentAmount)
598
+ return {
599
+ name: 'SOL',
600
+ symbol: 'SOL',
601
+ balance,
602
+ decimal: SOL_DECIMAL,
603
+ type: 'SOL',
604
+ }
605
+ })
606
+ const _getTokenBalance = async (address) => {
607
+ try {
608
+ return await this.getTokenBalance(address)
609
+ } catch (error) {
610
+ if (error.message && error.message.includes('could not find account')) {
611
+ return '0'
612
+ }
613
+ throw error
614
+ }
615
+ }
616
+
617
+ const resolveTokens = tokenAccounts.map(async (account) => {
618
+ const [_tokenMetaPlex, currentAmount, decimal] = await Promise.all([
619
+ this.getMetaplexMetadata(account.mint),
620
+ _getTokenBalance(account.address),
621
+ this.getDecimals(account.mint),
622
+ ])
623
+
624
+ const balance = computeBalance(account.amount, currentAmount)
625
+ const tokenMetaPlex = _tokenMetaPlex || { name: null, symbol: null }
626
+ return {
627
+ name: tokenMetaPlex.name,
628
+ symbol: tokenMetaPlex.symbol,
629
+ balance,
630
+ decimal,
631
+ type: 'TOKEN',
632
+ }
633
+ })
634
+
635
+ const accounts = await Promise.all([...resolveSols, ...resolveTokens])
636
+ accounts.forEach((account) => {
637
+ if (account.balance > 0) {
638
+ willReceive.push(account)
639
+ } else {
640
+ willSend.push(account)
641
+ }
642
+ })
643
+
644
+ return {
645
+ willReceive,
646
+ willSend,
647
+ }
648
+ }
649
+
650
+ /**
651
+ * Simulate transaction and return side effects
652
+ */
653
+ simulateAndRetrieveSideEffects = async (transaction, publicKey: string) => {
654
+ const { config, accountAddresses } = getTransactionSimulationParams(transaction)
655
+ const futureAccountsState = await this.simulateTransaction(transaction, config)
656
+ const { solAccounts, tokenAccounts } = filterAccountsByOwner(
657
+ futureAccountsState,
658
+ accountAddresses,
659
+ publicKey
660
+ )
661
+
662
+ return this.resolveSimulationSideEffects(solAccounts, tokenAccounts)
663
+ }
563
664
  }
564
665
 
565
666
  function isTokenSupported(mint: string) {