@exodus/solana-api 3.0.0 → 3.1.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/solana-api",
3
- "version": "3.0.0",
3
+ "version": "3.1.0",
4
4
  "description": "Exodus internal Solana asset API wrapper",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -29,7 +29,7 @@
29
29
  "@exodus/models": "^10.1.0",
30
30
  "@exodus/nfts-core": "^0.5.0",
31
31
  "@exodus/simple-retry": "^0.0.6",
32
- "@exodus/solana-lib": "^2.0.0",
32
+ "@exodus/solana-lib": "^2.1.0",
33
33
  "@exodus/solana-meta": "^1.0.7",
34
34
  "bn.js": "^4.11.0",
35
35
  "debug": "^4.1.1",
@@ -44,5 +44,5 @@
44
44
  "devDependencies": {
45
45
  "@exodus/assets-testing": "^1.0.0"
46
46
  },
47
- "gitHead": "44827e13fbd513ee9a0d7cec603d20fe89d0d80a"
47
+ "gitHead": "84f77ed9720dcdabb8057ed9170f45fcb4f9eff9"
48
48
  }
package/src/api.js CHANGED
@@ -9,6 +9,7 @@ import {
9
9
  SYSTEM_PROGRAM_ID,
10
10
  STAKE_PROGRAM_ID,
11
11
  TOKEN_PROGRAM_ID,
12
+ TOKEN_2022_PROGRAM_ID,
12
13
  SOL_DECIMAL,
13
14
  computeBalance,
14
15
  buildRawTransaction,
@@ -342,7 +343,9 @@ export class Api {
342
343
  .map((ix) => {
343
344
  const type = lodash.get(ix, 'parsed.type')
344
345
  const isTransferTx =
345
- ix.parsed && ix.program === 'spl-token' && ['transfer', 'transferChecked'].includes(type)
346
+ ix.parsed &&
347
+ ix.program === 'spl-token' &&
348
+ ['transfer', 'transferChecked', 'transferCheckedWithFee'].includes(type)
346
349
  const source = lodash.get(ix, 'parsed.info.source')
347
350
  const destination = lodash.get(ix, 'parsed.info.destination')
348
351
  const amount = Number(
@@ -449,7 +452,10 @@ export class Api {
449
452
  )
450
453
  const tokenTxs = lodash
451
454
  .filter(instructions, ({ program, type }) => {
452
- return program === 'spl-token' && ['transfer', 'transferChecked'].includes(type)
455
+ return (
456
+ program === 'spl-token' &&
457
+ ['transfer', 'transferChecked', 'transferCheckedWithFee'].includes(type)
458
+ )
453
459
  }) // get Token transfer: could have more than 1 instructions
454
460
  .map((ix) => {
455
461
  // add token details based on source/destination address
@@ -469,7 +475,7 @@ export class Api {
469
475
  token: tokenAccount,
470
476
  from: ix.source,
471
477
  to: ix.destination,
472
- amount: Number(ix.amount || lodash.get(ix, 'tokenAmount.amount', 0)), // supporting both types: transfer and transferChecked
478
+ amount: Number(ix.amount || lodash.get(ix, 'tokenAmount.amount', 0)), // supporting types: transfer, transferChecked, transferCheckedWithFee
473
479
  fee: isSending ? fee : 0, // in lamports
474
480
  }
475
481
  })
@@ -594,11 +600,21 @@ export class Api {
594
600
  }
595
601
 
596
602
  async getTokenAccountsByOwner(address, tokenTicker) {
597
- const { value: accountsList } = await this.rpcCall(
598
- 'getTokenAccountsByOwner',
599
- [address, { programId: TOKEN_PROGRAM_ID.toBase58() }, { encoding: 'jsonParsed' }],
600
- { address }
601
- )
603
+ const [{ value: standardTokenAccounts }, { value: token2022Accounts }] = await Promise.all([
604
+ this.rpcCall(
605
+ 'getTokenAccountsByOwner',
606
+ [address, { programId: TOKEN_PROGRAM_ID.toBase58() }, { encoding: 'jsonParsed' }],
607
+ { address }
608
+ ),
609
+ this.rpcCall(
610
+ 'getTokenAccountsByOwner',
611
+ [address, { programId: TOKEN_2022_PROGRAM_ID.toBase58() }, { encoding: 'jsonParsed' }],
612
+ { address }
613
+ ),
614
+ ])
615
+
616
+ // merge regular token and token2022 program tokens
617
+ const accountsList = [...standardTokenAccounts, ...token2022Accounts]
602
618
 
603
619
  const tokenAccounts = []
604
620
  for (const entry of accountsList) {
@@ -608,8 +624,15 @@ export class Api {
608
624
  const token = this.getTokenByAddress(mint) || {
609
625
  name: 'unknown',
610
626
  ticker: 'UNKNOWN',
627
+ decimals: 0,
611
628
  }
612
629
  const balance = lodash.get(account, 'data.parsed.info.tokenAmount.amount', '0')
630
+ const tokenProgram = lodash.get(account, 'owner', null) // TOKEN_PROGRAM_ID or TOKEN_2022_PROGRAM_ID
631
+ const { feeBasisPoints = 0, maximumFee = 0 } =
632
+ tokenProgram === TOKEN_2022_PROGRAM_ID.toBase58()
633
+ ? await this.getTokenFeeBasisPoints(mint)
634
+ : {}
635
+
613
636
  tokenAccounts.push({
614
637
  tokenAccountAddress: pubkey,
615
638
  owner: address,
@@ -617,6 +640,10 @@ export class Api {
617
640
  ticker: token.ticker,
618
641
  balance,
619
642
  mintAddress: mint,
643
+ tokenProgram,
644
+ decimals: token.decimals,
645
+ feeBasisPoints,
646
+ maximumFee,
620
647
  })
621
648
  }
622
649
 
@@ -674,7 +701,19 @@ export class Api {
674
701
 
675
702
  async isSpl(address) {
676
703
  const { owner } = await this.getAccountInfo(address)
677
- return owner === 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'
704
+ return [TOKEN_PROGRAM_ID.toBase58(), TOKEN_2022_PROGRAM_ID.toBase58()].includes(owner)
705
+ }
706
+
707
+ async getTokenFeeBasisPoints(address) {
708
+ // only for token-2022
709
+ const value = await this.getAccountInfo(address)
710
+ const { transferFeeBasisPoints, maximumFee } = lodash.get(
711
+ value,
712
+ 'data.parsed.info.extensions[0].state.newerTransferFee',
713
+ { transferFeeBasisPoints: 0, maximumFee: 0 }
714
+ )
715
+
716
+ return { feeBasisPoints: transferFeeBasisPoints, maximumFee }
678
717
  }
679
718
 
680
719
  async getMetaplexMetadata(tokenMintAddress) {
@@ -702,11 +741,10 @@ export class Api {
702
741
  lamports: value.lamports,
703
742
  }
704
743
 
705
- return account.owner === SYSTEM_PROGRAM_ID.toBase58()
706
- ? 'solana'
707
- : account.owner === TOKEN_PROGRAM_ID.toBase58()
708
- ? 'token'
709
- : null
744
+ if (account.owner === SYSTEM_PROGRAM_ID.toBase58()) return 'solana'
745
+ if (account.owner === TOKEN_PROGRAM_ID.toBase58()) return 'token'
746
+ if (account.owner === TOKEN_2022_PROGRAM_ID.toBase58()) return 'token-2022'
747
+ return null
710
748
  }
711
749
 
712
750
  async getTokenAddressOwner(address) {
@@ -722,7 +760,7 @@ export class Api {
722
760
 
723
761
  async isTokenAddress(address) {
724
762
  const type = await this.getAddressType(address)
725
- return type === 'token'
763
+ return ['token', 'token-2022'].includes(type)
726
764
  }
727
765
 
728
766
  async isSOLaddress(address) {
package/src/tx-send.js CHANGED
@@ -1,4 +1,9 @@
1
- import { createUnsignedTx, findAssociatedTokenAddress } from '@exodus/solana-lib'
1
+ import {
2
+ createUnsignedTx,
3
+ findAssociatedTokenAddress,
4
+ TOKEN_PROGRAM_ID,
5
+ TOKEN_2022_PROGRAM_ID,
6
+ } from '@exodus/solana-lib'
2
7
  import assert from 'minimalistic-assert'
3
8
 
4
9
  export const createAndBroadcastTXFactory =
@@ -65,7 +70,15 @@ export const createAndBroadcastTXFactory =
65
70
  let tokenParams = Object.create(null)
66
71
  if (isToken || customMintAddress) {
67
72
  const tokenMintAddress = customMintAddress || asset.mintAddress
68
- const tokenAddress = findAssociatedTokenAddress(address, tokenMintAddress)
73
+ const tokenProgram =
74
+ (await api.getAddressType(tokenMintAddress)) === 'token-2022'
75
+ ? TOKEN_2022_PROGRAM_ID
76
+ : TOKEN_PROGRAM_ID
77
+ const tokenAddress = findAssociatedTokenAddress(
78
+ address,
79
+ tokenMintAddress,
80
+ tokenProgram.toBase58()
81
+ )
69
82
  const [destinationAddressType, isAssociatedTokenAccountActive, fromTokenAccountAddresses] =
70
83
  await Promise.all([
71
84
  api.getAddressType(address),
@@ -83,6 +96,7 @@ export const createAndBroadcastTXFactory =
83
96
  isAssociatedTokenAccountActive,
84
97
  fromTokenAddresses,
85
98
  tokenStandard,
99
+ tokenProgram,
86
100
  }
87
101
  }
88
102