Skip to content

Commit

Permalink
adds classic asset balance to balances query
Browse files Browse the repository at this point in the history
  • Loading branch information
aristidesstaffieri committed Nov 28, 2023
1 parent bb78ef1 commit 6eef71e
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 66 deletions.
109 changes: 84 additions & 25 deletions src/service/mercury/helpers/transformers.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { OperationResult } from "@urql/core";
import { scValToNative, xdr } from "soroban-client";
import BigNumber from "bignumber.js";
import { NativeBalance } from "../../../helper/horizon-rpc";
import {
BASE_RESERVE,
BASE_RESERVE_MIN_COUNT,
NativeBalance,
} from "../../../helper/horizon-rpc";

// Transformers take an API response, and transform it/augment it for frontend consumption

Expand All @@ -19,7 +23,28 @@ interface AccountBalancesInterface {
}

interface MercuryAccountBalancesData {
entryUpdateByContractIdAndKey: {
accountObjectByPublicKey: {
nodes: {
accountByAccount: {
publickey: string;
};
nativeBalance: string;
numSubEntries: string;
}[];
};
balanceByPublicKey: {
nodes: {
assetByAsset: {
code: string;
issuer: string;
};
accountByAccount: {
publickey: string;
};
balance: string;
}[];
};
entryUpdateByContractIdAndKey?: {
nodes: {
contractId: string;
keyXdr: string;
Expand All @@ -40,8 +65,32 @@ const transformAccountBalances = async (
rawResponse: OperationResult<MercuryAccountBalancesData>,
tokenDetails: TokenDetails
) => {
const data = rawResponse?.data?.entryUpdateByContractIdAndKey.nodes || [];
const formattedBalances = data.map((entry) => {
const tokenBalanceData =
rawResponse?.data?.entryUpdateByContractIdAndKey?.nodes || [];
const accountObjectData =
rawResponse?.data?.accountObjectByPublicKey.nodes || [];
const classicBalanceData = rawResponse?.data?.balanceByPublicKey.nodes || [];

const accountObject = accountObjectData[0];
// TODO: get these into query
const numSponsoring = 0;
const numSponsored = 0;
const sellingLiabilities = 0;

const accountBalance = {
native: {
token: { type: "native", code: "XLM" },
total: new BigNumber(accountObject.nativeBalance),
available: new BigNumber(BASE_RESERVE_MIN_COUNT)
.plus(accountObject.numSubEntries)
.plus(numSponsoring)
.minus(numSponsored)
.times(BASE_RESERVE)
.plus(sellingLiabilities),
},
};

const formattedBalances = tokenBalanceData.map((entry) => {
const details = tokenDetails[entry.contractId];
const totalScVal = xdr.ScVal.fromXDR(Buffer.from(entry.valueXdr, "base64"));
return {
Expand All @@ -52,33 +101,43 @@ const transformAccountBalances = async (
});

const balances = formattedBalances.reduce((prev, curr) => {
if (curr.symbol === "XLM") {
prev["native"] = {
token: { type: "native", code: "XLM" },
total: new BigNumber(curr.total),
available: new BigNumber(curr.total), // TODO: how to get available for xlm?
} as NativeBalance;
}
if (curr.contractId) {
prev[`${curr.symbol}:${curr.contractId}`] = {
token: {
code: curr.symbol,
issuer: {
key: curr.contractId,
},
prev[`${curr.symbol}:${curr.contractId}`] = {
token: {
code: curr.symbol,
issuer: {
key: curr.contractId,
},
decimals: curr.decimals,
total: new BigNumber(curr.total),
available: new BigNumber(curr.total),
};
}
},
decimals: curr.decimals,
total: new BigNumber(curr.total),
available: new BigNumber(curr.total),
};
return prev;
}, {} as NonNullable<AccountBalancesInterface["balances"]>);

const classicBalances = classicBalanceData.reduce((prev, curr) => {
prev[`${curr.assetByAsset.code}:${curr.assetByAsset.issuer}`] = {
token: {
code: curr.assetByAsset.code,
issuer: {
key: curr.assetByAsset.issuer,
},
},
decimals: "7",
total: new BigNumber(curr.balance),
available: new BigNumber(curr.balance),
};
return prev;
}, {} as NonNullable<AccountBalancesInterface["balances"]>);

return {
balances,
balances: {
...accountBalance,
...classicBalances,
...balances,
},
isFunded: true,
subentryCount: 0, // TODO: Mercury will index this with account subs, and will add to query
subentryCount: accountObject.numSubEntries,
};
};

Expand Down
45 changes: 5 additions & 40 deletions src/service/mercury/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -473,17 +473,14 @@ export class MercuryClient {
contractIds: string[],
network: NetworkNames
) => {
if (contractIds.length < 1) {
return {
data: [],
error: null,
};
}
// TODO: once classic subs include balance, add query
try {
const getData = async () => {
const response = await this.urqlClient.query(
query.getAccountBalances(this.tokenBalanceKey(pubKey), contractIds),
query.getAccountBalances(
pubKey,
this.tokenBalanceKey(pubKey),
contractIds
),
{}
);
const errorMessage = getGraphQlError(response.error);
Expand Down Expand Up @@ -527,38 +524,6 @@ export class MercuryClient {
contractIds,
network
);
// const mockResponse = {
// balances: {
// native: {
// token: { type: "native", code: "XLM" },
// total: new BigNumber(4),
// available: new BigNumber(1),
// },
// ["DT:CCWAMYJME4H5CKG7OLXGC2T4M6FL52XCZ3OQOAV6LL3GLA4RO4WH3ASP"]: {
// token: {
// code: "DT",
// issuer: {
// key: "CCWAMYJME4H5CKG7OLXGC2T4M6FL52XCZ3OQOAV6LL3GLA4RO4WH3ASP",
// },
// },
// decimals: 7,
// total: new BigNumber("10"),
// available: new BigNumber("10"),
// },
// ["USDC:GCK3D3V2XNLLKRFGFFFDEJXA4O2J4X36HET2FE446AV3M4U7DPHO3PEM"]: {
// token: {
// code: "USDC",
// issuer: {
// key: "GCK3D3V2XNLLKRFGFFFDEJXA4O2J4X36HET2FE446AV3M4U7DPHO3PEM",
// },
// },
// total: new BigNumber("100"),
// available: new BigNumber("100"),
// },
// },
// isFunded: true,
// subentryCount: 1
// }

return {
data,
Expand Down
31 changes: 30 additions & 1 deletion src/service/mercury/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,37 @@ export const query = {
}
}
`,
getAccountBalances: (ledgerKey: string, contractIds: string[]) => `
getAccountBalances: (
pubKey: string,
ledgerKey: string,
contractIds: string[]
) => `
query AccountBalances {
accountObjectByPublicKey(
publicKeyText: "${pubKey}"
) {
nodes {
accountByAccount {
publickey
}
nativeBalance
numSubEntries
}
}
balanceByPublicKey(
publicKeyText: "${pubKey}"
) {
nodes {
assetByAsset {
code
issuer
}
accountByAccount {
publickey
}
balance
}
}
${contractIds.map(
(id) =>
`
Expand Down

0 comments on commit 6eef71e

Please sign in to comment.