diff --git a/src/containers/Accounts/AMM/AMMAccounts/index.tsx b/src/containers/Accounts/AMM/AMMAccounts/index.tsx
index d066637d5..1c9407024 100644
--- a/src/containers/Accounts/AMM/AMMAccounts/index.tsx
+++ b/src/containers/Accounts/AMM/AMMAccounts/index.tsx
@@ -5,8 +5,9 @@ import { useLanguage } from '../../../shared/hooks'
import '../../styles.scss'
import { formatAmount } from '../../../../rippled/lib/txSummary/formatAmount'
import {
- getAccountTransactions,
+ getAccountInfo,
getAMMInfo,
+ getLedgerEntry,
} from '../../../../rippled/lib/rippled'
import { Tabs } from '../../../shared/components/Tabs'
import { useAnalytics } from '../../../shared/analytics'
@@ -26,14 +27,6 @@ import { ACCOUNT_ROUTE } from '../../../App/routes'
const getErrorMessage = (error: string) =>
ERROR_MESSAGES[error] || ERROR_MESSAGES.default
-function findAMMCreate(txs: [any]) {
- const ammCreate = txs.filter((tx) => tx.tx.TransactionType === 'AMMCreate')
-
- if (ammCreate.length < 1) throw new Error('Could not find AMM Create')
-
- return ammCreate[0].tx
-}
-
function renderError(error: any) {
const message = getErrorMessage(error.code)
return (
@@ -70,50 +63,47 @@ export const AMMAccounts = () => {
Get the first account transaction which in this case should be AMMCreate. From this we get
the two assets in the asset pool.
*/
- return (
- getAccountTransactions(rippledSocket, accountId, 1, undefined, true)
- .then((tData) => {
- const tx = findAMMCreate(tData.transactions)
- asset1 = formatAsset(tx.Amount)
- asset2 = formatAsset(tx.Amount2)
-
- // if one of the assets is XRP, make sure it's the second one
- if (asset1.currency === 'XRP') {
- const temp = asset2
- asset2 = asset1
- asset1 = temp
- }
-
- return getAMMInfo(rippledSocket, asset1, asset2)
- })
-
- /*
- Use the assets to get the AMM Info.
- */
- .then((ammDataWrapper) => {
- ammData = ammDataWrapper.amm
- const balance = formatAmount(ammData.amount)
- const balance2 = formatAmount(ammData.amount2)
-
- const ammInfo: AmmDataType = {
- balance,
- balance2,
- tradingFee: ammData.trading_fee,
- lpBalance: ammData.lp_token.value,
- accountId,
- language,
- }
-
- return ammInfo
- })
- .catch((e) => {
- trackException(
- `Error setting up amm account --- ${JSON.stringify(e)}`,
- )
-
- throw e
- })
- )
+ return getAccountInfo(rippledSocket, accountId)
+ .then((accountInfo) =>
+ getLedgerEntry(rippledSocket, { index: accountInfo.AMMID })
+ .then((ammLedgerEntry) => {
+ asset1 = formatAsset(ammLedgerEntry.node.Asset)
+ asset2 = formatAsset(ammLedgerEntry.node.Asset2)
+
+ // if one of the assets is XRP, make sure it's the second one
+ if (asset1.currency === 'XRP') {
+ const temp = asset2
+ asset2 = asset1
+ asset1 = temp
+ }
+
+ return getAMMInfo(rippledSocket, asset1, asset2)
+ })
+ /*
+ Use the assets to get the AMM Info.
+ */
+ .then((ammDataWrapper) => {
+ ammData = ammDataWrapper.amm
+ const balance = formatAmount(ammData.amount)
+ const balance2 = formatAmount(ammData.amount2)
+
+ const ammInfo: AmmDataType = {
+ balance,
+ balance2,
+ tradingFee: ammData.trading_fee,
+ lpBalance: ammData.lp_token.value,
+ accountId,
+ language,
+ }
+
+ return ammInfo
+ }),
+ )
+ .catch((e) => {
+ trackException(`Error setting up amm account --- ${JSON.stringify(e)}`)
+
+ throw e
+ })
})
useEffect(
diff --git a/src/containers/Accounts/AMM/AMMAccounts/test/AMMAccounts.test.tsx b/src/containers/Accounts/AMM/AMMAccounts/test/AMMAccounts.test.tsx
index 0deefa651..8f3a4f260 100644
--- a/src/containers/Accounts/AMM/AMMAccounts/test/AMMAccounts.test.tsx
+++ b/src/containers/Accounts/AMM/AMMAccounts/test/AMMAccounts.test.tsx
@@ -9,12 +9,18 @@ import { AMMAccounts } from '../index'
import { flushPromises, QuickHarness } from '../../../../test/utils'
import { ACCOUNT_ROUTE } from '../../../../App/routes'
-function setSpy(accountTransactions: any, ammInfo: any) {
+function setSpy(accountInfo: any, getLedgerEntry: any, ammInfo: any) {
+ const spyAccountInfo = jest.spyOn(rippled, 'getAccountInfo')
+ const spyLedgerEntry = jest.spyOn(rippled, 'getLedgerEntry')
const spyInfo = jest.spyOn(rippled, 'getAMMInfo')
- const spyTransactions = jest.spyOn(rippled, 'getAccountTransactions')
- spyTransactions.mockReturnValue(
+ spyAccountInfo.mockReturnValue(
new Promise((resolve) => {
- resolve(accountTransactions)
+ resolve(accountInfo)
+ }),
+ )
+ spyLedgerEntry.mockReturnValue(
+ new Promise((resolve) => {
+ resolve(getLedgerEntry)
}),
)
spyInfo.mockReturnValue(
@@ -26,27 +32,100 @@ function setSpy(accountTransactions: any, ammInfo: any) {
describe('AMM Account Page', () => {
const TEST_ACCOUNT_ID = 'rTEST_ACCOUNT'
- const accountTransactions: any = {
- transactions: [
- {
- tx: {
- Amount: '10000000000',
- Amount2: { currency: 'USD', amount: '100000', issuer: 'SOLO' },
- TransactionType: 'AMMCreate',
+ const accountInfo: any = {
+ AMMID: '0017D8D412779284FDA6A63CEBEADD43BC2FEF37181C3C234ADAC9EFBB5FDB53',
+ Account: 'rJbt6ryq1TzikBuvVQDaxVLqL77eJeibsj',
+ Balance: '10000000',
+ Flags: 26214400,
+ LedgerEntryType: 'AccountRoot',
+ OwnerCount: 1,
+ PreviousTxnID:
+ '2A9F2B8D74CBECFF339BBD5CD9E42468984D3D8AA5D521B9610F31B014629DC2',
+ PreviousTxnLgrSeq: 58180,
+ Sequence: 58180,
+ index: '115CA30FD281E3265AA22F563B4ADE4BD15A6107F1E5105056F191882BE78FC4',
+ }
+
+ const ledgerEntry: any = {
+ index: '0017D8D412779284FDA6A63CEBEADD43BC2FEF37181C3C234ADAC9EFBB5FDB53',
+ ledger_hash:
+ '6C1914FF5966D2FD060B92B07A30A303369F28132DB5E8D73BED4FFC8A372EF2',
+ ledger_index: 285601,
+ node: {
+ Account: 'rJbt6ryq1TzikBuvVQDaxVLqL77eJeibsj',
+ Asset: {
+ currency: 'XRP',
+ },
+ Asset2: {
+ currency: 'USD',
+ issuer: 'rJd9Ti4TF2Mrn268LW7sSw8E16J4hYzMiD',
+ },
+ AuctionSlot: {
+ Account: 'rJd9Ti4TF2Mrn268LW7sSw8E16J4hYzMiD',
+ Expiration: 745719332,
+ Price: {
+ currency: '03930D02208264E2E40EC1B0C09E4DB96EE197B1',
+ issuer: 'rJbt6ryq1TzikBuvVQDaxVLqL77eJeibsj',
+ value: '0',
},
},
- ],
+ Flags: 0,
+ LPTokenBalance: {
+ currency: '03930D02208264E2E40EC1B0C09E4DB96EE197B1',
+ issuer: 'rJbt6ryq1TzikBuvVQDaxVLqL77eJeibsj',
+ value: '10000',
+ },
+ LedgerEntryType: 'AMM',
+ VoteSlots: [
+ {
+ VoteEntry: {
+ Account: 'rJd9Ti4TF2Mrn268LW7sSw8E16J4hYzMiD',
+ VoteWeight: 100000,
+ },
+ },
+ ],
+ index: '0017D8D412779284FDA6A63CEBEADD43BC2FEF37181C3C234ADAC9EFBB5FDB53',
+ },
+ validated: true,
}
const ammInfo: any = {
amm: {
- amount: '10000000000',
- amount2: { currency: 'USD', value: '100000' },
- trading_fee: 10,
+ account: 'rJbt6ryq1TzikBuvVQDaxVLqL77eJeibsj',
+ amount: '10000000',
+ amount2: {
+ currency: 'USD',
+ issuer: 'rJd9Ti4TF2Mrn268LW7sSw8E16J4hYzMiD',
+ value: '10',
+ },
+ asset2_frozen: false,
+ auction_slot: {
+ account: 'rJd9Ti4TF2Mrn268LW7sSw8E16J4hYzMiD',
+ discounted_fee: 0,
+ expiration: '2023-08-19T00:15:32+0000',
+ price: {
+ currency: '03930D02208264E2E40EC1B0C09E4DB96EE197B1',
+ issuer: 'rJbt6ryq1TzikBuvVQDaxVLqL77eJeibsj',
+ value: '0',
+ },
+ time_interval: 20,
+ },
lp_token: {
- value: '8989',
+ currency: '03930D02208264E2E40EC1B0C09E4DB96EE197B1',
+ issuer: 'rJbt6ryq1TzikBuvVQDaxVLqL77eJeibsj',
+ value: '10000',
},
+ trading_fee: 0,
+ vote_slots: [
+ {
+ account: 'rJd9Ti4TF2Mrn268LW7sSw8E16J4hYzMiD',
+ trading_fee: 0,
+ vote_weight: 100000,
+ },
+ ],
},
+ ledger_current_index: 285641,
+ validated: false,
}
const createWrapper = () =>
@@ -59,8 +138,8 @@ describe('AMM Account Page', () => {
,
)
- it('renders AMM account page when TVL not present', async () => {
- setSpy(accountTransactions, ammInfo)
+ it('renders AMM account page', async () => {
+ setSpy(accountInfo, ledgerEntry, ammInfo)
const wrapper = createWrapper()
await flushPromises()
@@ -71,7 +150,7 @@ describe('AMM Account Page', () => {
})
it('shows error when amm info data is formatted incorrectly', async () => {
- setSpy(accountTransactions, 'ammInfo')
+ setSpy(accountInfo, ledgerEntry, 'ammInfo')
const wrapper = await createWrapper()
await flushPromises()
@@ -82,12 +161,34 @@ describe('AMM Account Page', () => {
wrapper.unmount()
})
- it('shows error when account transactions data is formatted incorrectly', async () => {
- const accTransBad: any = {
- transactions: [],
+ it('shows error when account_info has no AMMID', async () => {
+ const badAccountInfo: any = {
+ ...accountInfo,
+ }
+
+ delete badAccountInfo.AMMID
+
+ const badLedgerEntry = {
+ error: 'invalidParams',
+ error_code: 31,
+ error_message: 'indexMalformed',
+ status: 'error',
+ type: 'response',
+ request: {
+ command: 'ledger_entry',
+ index: '',
+ ledger_index: 'validated',
+ },
+ warnings: [
+ {
+ id: 2001,
+ message:
+ "This is a clio server. clio only serves validated data. If you want to talk to rippled, include 'ledger_index':'current' in your request",
+ },
+ ],
}
- setSpy(accTransBad, ammInfo)
+ setSpy(badAccountInfo, badLedgerEntry, ammInfo)
const wrapper = createWrapper()
await flushPromises()
diff --git a/src/containers/Accounts/AccountsRouter.tsx b/src/containers/Accounts/AccountsRouter.tsx
index 052562b5c..1141bff59 100644
--- a/src/containers/Accounts/AccountsRouter.tsx
+++ b/src/containers/Accounts/AccountsRouter.tsx
@@ -13,7 +13,7 @@ import NoMatch from '../NoMatch'
import { Accounts } from './index'
import { ERROR_MESSAGES } from './Errors'
import { Loader } from '../shared/components/Loader'
-import { ACCOUNT_FLAGS, Error } from '../../rippled/lib/utils'
+import { Error } from '../../rippled/lib/utils'
import { BAD_REQUEST } from '../shared/utils'
const getErrorMessage = (error: any) =>
@@ -31,10 +31,6 @@ function renderError(error: any) {
export const AccountsRouter = () => {
const { id: accountId = '' } = useParams<{ id: string }>()
const rippledSocket = useContext(SocketContext)
- const flags: any = Object.entries(ACCOUNT_FLAGS).reduce(
- (all, [key, value]) => ({ ...all, [value]: key }),
- {},
- )
const { data: comp, error } = useQuery([accountId], () => {
let classicAddress = accountId
@@ -49,7 +45,7 @@ export const AccountsRouter = () => {
return (
getAccountInfo(rippledSocket, classicAddress)
.then((data: any) => {
- if (data.Flags & flags.lsfAMM) {
+ if (data.AMMID) {
return
}
return
diff --git a/src/rippled/lib/rippled.js b/src/rippled/lib/rippled.js
index 7420909d3..e6b5ac6b3 100644
--- a/src/rippled/lib/rippled.js
+++ b/src/rippled/lib/rippled.js
@@ -74,6 +74,70 @@ const getLedger = (rippledSocket, parameters) => {
})
}
+// get ledger_entry
+const getLedgerEntry = (rippledSocket, { index }) => {
+ const request = {
+ command: 'ledger_entry',
+ index,
+ ledger_index: 'validated',
+ }
+
+ return query(rippledSocket, request).then((resp) => {
+ if (resp.error_message === 'entryNotFound') {
+ throw new Error('ledger entry not found', 404)
+ }
+
+ if (resp.error_message === 'invalidParams') {
+ throw new Error('invalidParams for ledger_entry', 404)
+ }
+
+ if (resp.error_message === 'lgrNotFound') {
+ throw new Error('invalid ledger index/hash', 400)
+ }
+
+ if (resp.error_message === 'malformedAddress') {
+ throw new Error(
+ 'The ledger_entry request improperly specified an Address field.',
+ 404,
+ )
+ }
+
+ if (resp.error_message === 'malformedCurrency') {
+ throw new Error(
+ 'The ledger_entry request improperly specified a Currency Code field.',
+ 404,
+ )
+ }
+
+ if (resp.error_message === 'malformedOwner') {
+ throw new Error(
+ 'The ledger_entry request improperly specified the escrow.owner sub-field.',
+ 404,
+ )
+ }
+
+ if (resp.error_message === 'malformedRequest') {
+ throw new Error(
+ 'The ledger_entry request provided an invalid combination of fields, or provided the wrong type for one or more fields.',
+ 404,
+ )
+ }
+
+ if (resp.error_message === 'unknownOption') {
+ throw new Error(
+ 'The fields provided in the ledger_entry request did not match any of the expected request formats.',
+ 404,
+ )
+ }
+
+ if (resp.error_message) {
+ throw new Error(resp.error_message, 500)
+ }
+
+ return resp
+ })
+}
+
// get transaction
const getTransaction = (rippledSocket, txHash) => {
const params = {
@@ -279,7 +343,6 @@ const getAccountTransactions = (
account,
limit = 20,
marker = '',
- reverseOrder = false,
) => {
const markerComponents = marker.split('.')
const ledger = parseInt(markerComponents[0], 10)
@@ -288,7 +351,6 @@ const getAccountTransactions = (
command: 'account_tx',
account,
limit,
- forward: reverseOrder,
ledger_index_max: -1,
ledger_index_min: -1,
marker: marker
@@ -481,6 +543,7 @@ const getAMMInfo = (rippledSocket, asset, asset2) => {
export {
getLedger,
+ getLedgerEntry,
getTransaction,
getAccountInfo,
getAccountEscrows,
diff --git a/src/rippled/lib/utils.js b/src/rippled/lib/utils.js
index d801452f6..59fedbee3 100644
--- a/src/rippled/lib/utils.js
+++ b/src/rippled/lib/utils.js
@@ -19,7 +19,6 @@ export const ACCOUNT_FLAGS = {
0x08000000: 'lsfDisallowIncomingCheck',
0x10000000: 'lsfDisallowIncomingPayChan',
0x20000000: 'lsfDisallowIncomingTrustline',
- 0x40000000: 'lsfAMM',
0x80000000: 'lsfAllowTrustLineClawback',
}
const NFT_FLAGS = {