@exodus/solana-api 1.2.26 → 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 +3 -3
- package/src/index.js +71 -20
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/solana-api",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
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.
|
|
17
|
+
"@exodus/solana-lib": "^1.2.27",
|
|
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": "
|
|
25
|
+
"gitHead": "3f87eb48ecfdc13665102dacae7ca67dc8f1012e"
|
|
26
26
|
}
|
package/src/index.js
CHANGED
|
@@ -90,7 +90,7 @@ class Api {
|
|
|
90
90
|
async getConfirmedSignaturesForAddress(address: string, { until, before, limit } = {}): any {
|
|
91
91
|
until = until || undefined
|
|
92
92
|
return this.api.post({
|
|
93
|
-
method: '
|
|
93
|
+
method: 'getSignaturesForAddress',
|
|
94
94
|
params: [address, { until, before, limit }],
|
|
95
95
|
})
|
|
96
96
|
}
|
|
@@ -160,8 +160,8 @@ class Api {
|
|
|
160
160
|
txDetails: Object,
|
|
161
161
|
tokenAccountsByOwner: ?Array
|
|
162
162
|
): Object {
|
|
163
|
-
const { fee } = txDetails.meta
|
|
164
|
-
let { instructions } = txDetails.transaction.message
|
|
163
|
+
const { fee, preTokenBalances, postTokenBalances } = txDetails.meta
|
|
164
|
+
let { instructions, accountKeys } = txDetails.transaction.message
|
|
165
165
|
instructions = instructions
|
|
166
166
|
.filter((ix) => ix.parsed) // only known instructions
|
|
167
167
|
.map((ix) => ({
|
|
@@ -179,7 +179,7 @@ class Api {
|
|
|
179
179
|
const stakeWithdraw = lodash.find(instructions, { program: 'stake', type: 'withdraw' })
|
|
180
180
|
const stakeUndelegate = lodash.find(instructions, { program: 'stake', type: 'deactivate' })
|
|
181
181
|
|
|
182
|
-
let tx
|
|
182
|
+
let tx = {}
|
|
183
183
|
if (solanaTx) {
|
|
184
184
|
// Solana tx
|
|
185
185
|
const isSending = ownerAddress === solanaTx.source
|
|
@@ -271,13 +271,62 @@ class Api {
|
|
|
271
271
|
}
|
|
272
272
|
})
|
|
273
273
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
274
|
+
if (tokenTxs.length) {
|
|
275
|
+
// found spl-token simple transfer/transferChecked instruction
|
|
276
|
+
// .reduce to sum/sub (based on isSending) all the same tokens amount (From instructions -> 1 single tx)
|
|
277
|
+
tx = tokenTxs.reduce((finalTx, ix) => {
|
|
278
|
+
if (!ix) return finalTx // skip null instructions
|
|
279
|
+
if (!finalTx.token) return ix // init finalTx (support just 1 token type per tx)
|
|
280
|
+
if (finalTx.token.ticker === ix.token.ticker) finalTx.amount += ix.amount
|
|
281
|
+
return finalTx
|
|
282
|
+
}, {})
|
|
283
|
+
} else if (preTokenBalances && postTokenBalances) {
|
|
284
|
+
// probably a DEX program is involved (multiple instructions), compute balance changes
|
|
285
|
+
|
|
286
|
+
const accountIndexes = lodash.mapKeys(accountKeys, (x, i) => i)
|
|
287
|
+
Object.values(accountIndexes).forEach((acc) => {
|
|
288
|
+
// filter by ownerAddress
|
|
289
|
+
const hasKnownOwner = !!lodash.find(tokenAccountsByOwner, {
|
|
290
|
+
tokenAccountAddress: acc.pubkey,
|
|
291
|
+
})
|
|
292
|
+
acc.owner = hasKnownOwner ? ownerAddress : null
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
// group by owner and supported token
|
|
296
|
+
const preBalances = preTokenBalances.filter((t) => {
|
|
297
|
+
return accountIndexes[t.accountIndex].owner === ownerAddress && isTokenSupported(t.mint)
|
|
298
|
+
})
|
|
299
|
+
const postBalances = postTokenBalances.filter((t) => {
|
|
300
|
+
return accountIndexes[t.accountIndex].owner === ownerAddress && isTokenSupported(t.mint)
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
if (preBalances.length && preBalances.length === postBalances.length) {
|
|
304
|
+
// parse and compute pre-balances/post-balances difference (1 token per tx spported at the moment)
|
|
305
|
+
const amount =
|
|
306
|
+
Number(lodash.get(postBalances, '[0].uiTokenAmount.amount', 0)) -
|
|
307
|
+
Number(lodash.get(preBalances, '[0].uiTokenAmount.amount', 0))
|
|
308
|
+
const isSending = Math.sign(amount) <= 0
|
|
309
|
+
|
|
310
|
+
const mint = lodash.get(postBalances, '[0].mint', '')
|
|
311
|
+
const { tokenName, ticker } = tokens.find(({ mintAddress }) => mintAddress === mint) || {
|
|
312
|
+
tokenName: 'unknown',
|
|
313
|
+
ticker: 'UNKNOWN',
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
tx = {
|
|
317
|
+
owner: isSending ? ownerAddress : TOKEN_PROGRAM_ID.toBase58(),
|
|
318
|
+
token: {
|
|
319
|
+
tokenAccountAddress: '', // token account is closed after the swap
|
|
320
|
+
tokenName,
|
|
321
|
+
ticker,
|
|
322
|
+
},
|
|
323
|
+
from: isSending ? ownerAddress : TOKEN_PROGRAM_ID.toBase58(),
|
|
324
|
+
to: ownerAddress, // DEX always interact with the owner address
|
|
325
|
+
amount,
|
|
326
|
+
fee: isSending ? fee : 0, // in lamports
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
281
330
|
}
|
|
282
331
|
|
|
283
332
|
// How tokens tx are parsed:
|
|
@@ -379,6 +428,12 @@ class Api {
|
|
|
379
428
|
: null
|
|
380
429
|
}
|
|
381
430
|
|
|
431
|
+
async getTokenAddressOwner(address: string) {
|
|
432
|
+
const value = await this.getAccountInfo(address)
|
|
433
|
+
const owner = lodash.get(value, 'data.parsed.info.owner', null)
|
|
434
|
+
return owner
|
|
435
|
+
}
|
|
436
|
+
|
|
382
437
|
async getAddressMint(address) {
|
|
383
438
|
const value = await this.getAccountInfo(address)
|
|
384
439
|
const mintAddress = lodash.get(value, 'data.parsed.info.mint', null) // token mint
|
|
@@ -443,18 +498,10 @@ class Api {
|
|
|
443
498
|
return { accounts, totalStake, locked, withdrawable, pending }
|
|
444
499
|
}
|
|
445
500
|
|
|
446
|
-
async getInflationReward(stakingAddresses: Array, epoch: number) {
|
|
447
|
-
const rewards = await this.api.post({
|
|
448
|
-
method: 'getInflationReward',
|
|
449
|
-
params: [stakingAddresses, { epoch }],
|
|
450
|
-
})
|
|
451
|
-
|
|
452
|
-
return rewards
|
|
453
|
-
}
|
|
454
|
-
|
|
455
501
|
async getRewards(stakingAddresses = []) {
|
|
456
502
|
if (!stakingAddresses.length) return 0
|
|
457
503
|
|
|
504
|
+
// custom endpoint!
|
|
458
505
|
const rewards = await this.request(`rewards?addresses=${stakingAddresses.join(',')}`)
|
|
459
506
|
.get()
|
|
460
507
|
.error(500, () => ({})) // addresses not found
|
|
@@ -494,4 +541,8 @@ class Api {
|
|
|
494
541
|
}
|
|
495
542
|
}
|
|
496
543
|
|
|
544
|
+
function isTokenSupported(mint: string) {
|
|
545
|
+
return !!tokens.find(({ mintAddress }) => mintAddress === mint)
|
|
546
|
+
}
|
|
547
|
+
|
|
497
548
|
export default new Api()
|