@lombard.finance/sdk 3.6.2 → 3.6.3

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": "@lombard.finance/sdk",
3
- "version": "3.6.2",
3
+ "version": "3.6.3",
4
4
  "dependencies": {
5
5
  "@lombard.finance/sdk-common": "^3.0.0",
6
6
  "viem": "^2.23.15",
package/src/index.ts CHANGED
@@ -30,7 +30,16 @@ export * from './utils/satoshi';
30
30
 
31
31
  // Metrics:
32
32
  export { getLBTCStats } from './metrics/get-lbtc-stats';
33
- export { getRewardsInfo } from './metrics/get-rewards-info';
33
+
34
+ export {
35
+ getPositionsSummary,
36
+ type PositionsSummary,
37
+ } from './metrics/get-positions-summary';
38
+ export { getApy, type LbtcApy } from './metrics/get-lbtc-apy';
39
+ export {
40
+ getAdditionalRewards,
41
+ type RewardsDistribution,
42
+ } from './metrics/get-additional-rewards';
34
43
 
35
44
  // Re-exports:
36
45
  export type { Address, EIP1193Provider } from 'viem';
@@ -0,0 +1,68 @@
1
+ import { Address } from 'viem';
2
+ import axios from 'axios';
3
+ import { getApiConfig } from '../common/api-config';
4
+ import { IEnvParam } from '../common/parameters';
5
+ import BigNumber from 'bignumber.js';
6
+
7
+ type Response = {
8
+ btc_distributed: { name: string; amount: number }[];
9
+ btc_undistributed: { name: string; amount: number }[];
10
+ };
11
+
12
+ export type RewardsDistribution = {
13
+ /**
14
+ * List of campaigns where rewards have been successfully distributed.
15
+ */
16
+ distributed: {
17
+ /** Name of the reward campaign. */
18
+ name: string;
19
+ /** Amount of BTC distributed for this campaign. */
20
+ amount: BigNumber;
21
+ }[];
22
+
23
+ /**
24
+ * List of campaigns where rewards are pending or not yet distributed.
25
+ */
26
+ undistributed: {
27
+ /** Name of the reward campaign. */
28
+ name: string;
29
+ /** Amount of BTC yet to be distributed. */
30
+ amount: BigNumber;
31
+ }[];
32
+ };
33
+
34
+ /**
35
+ * Retrieves additional rewards that have been distributed or are pending
36
+ * for a specific account.
37
+ */
38
+ export async function getAdditionalRewards({
39
+ account,
40
+ env,
41
+ }: {
42
+ account: Address;
43
+ } & IEnvParam) {
44
+ if (!account) {
45
+ throw new Error('Missing account address');
46
+ }
47
+
48
+ const { baseApiUrl } = getApiConfig(env);
49
+
50
+ const url = `${baseApiUrl}/api/v1/analytics/${account}/additional-rewards`;
51
+ const { data } = await axios.get<Response>(url);
52
+
53
+ const distribution: RewardsDistribution = {
54
+ distributed: data.btc_distributed.map(d => ({
55
+ amount: BigNumber(d.amount),
56
+ name: d.name,
57
+ })),
58
+ undistributed: data.btc_undistributed.map(u => ({
59
+ amount: BigNumber(u.amount),
60
+ name: u.name,
61
+ })),
62
+ };
63
+
64
+ return distribution;
65
+ }
66
+
67
+ // url: https://bft-dev.stage.lombard.finance/api/v1/analytics/0x2513196b4fD01Ed5888d1dB49AB9a42208E9fF90/additional-rewards
68
+ // {"btc_distributed":[{"name":"ledger", "amount":0.7691864317643695}], "btc_undistributed":[{"name":"ledger", "amount":0.5699985451505658}]}
@@ -0,0 +1,47 @@
1
+ import axios from 'axios';
2
+ import { Address, zeroAddress } from 'viem';
3
+ import BigNumber from 'bignumber.js';
4
+ import { getApiConfig } from '../common/api-config';
5
+ import { IEnvParam } from '../common/parameters';
6
+
7
+ type Response = {
8
+ lbtc_base_apy: number;
9
+ lbtc_effective_apy: number;
10
+ };
11
+
12
+ export type LbtcApy = {
13
+ /**
14
+ * The base APY for LBTC, representing the nominal yield without any bonuses
15
+ * or adjustments.
16
+ */
17
+ baseApy: BigNumber;
18
+ /**
19
+ * The effective APY for LBTC, including any additional rewards,
20
+ * compounding effects, or protocol-specific incentives.
21
+ */
22
+ effectiveApy: BigNumber;
23
+ };
24
+
25
+ /** Returns the current APY (annual percentage yield) for LBTC. */
26
+ export async function getApy({
27
+ account,
28
+ env,
29
+ }: {
30
+ /** The optional account address. Pass it for more accurate APY data. */
31
+ account?: Address;
32
+ } & IEnvParam) {
33
+ const { baseApiUrl } = getApiConfig(env);
34
+
35
+ const url = `${baseApiUrl}/api/v1/analytics/${account || zeroAddress}/apy`;
36
+ const { data } = await axios.get<Response>(url);
37
+
38
+ const apy: LbtcApy = {
39
+ baseApy: BigNumber(data.lbtc_base_apy),
40
+ effectiveApy: BigNumber(data.lbtc_effective_apy),
41
+ };
42
+
43
+ return apy;
44
+ }
45
+
46
+ // url: https://bft-dev.stage.lombard.finance/api/v1/analytics/0x2513196b4fD01Ed5888d1dB49AB9a42208E9fF90/apy
47
+ // {"lbtc_base_apy":0.18849167223827507, "lbtc_effective_apy":0.6828761605761976}
@@ -7,10 +7,6 @@ type LBTCStatsResponse = { price: number; supply: number; tvl: number }[];
7
7
 
8
8
  type LBTCHoldersResponse = number;
9
9
 
10
- type StakingStatsResponse = {
11
- apr: number;
12
- };
13
-
14
10
  type Stats = {
15
11
  /** The BTC price */
16
12
  price: BigNumber;
@@ -22,8 +18,6 @@ type Stats = {
22
18
  holders: BigNumber;
23
19
  /** The total (historical) number of LBTC holders */
24
20
  historicalHolders: BigNumber;
25
- /** The staking APR */
26
- apr: BigNumber | undefined;
27
21
  };
28
22
 
29
23
  /** Gets the Lombard's TVL. */
@@ -32,7 +26,6 @@ export async function getLBTCStats(
32
26
  ) {
33
27
  const env = parameters?.env;
34
28
  const partnerId = parameters?.partnerId;
35
- const accountAddress = parameters?.accountAddress;
36
29
 
37
30
  const { bffApiUrl } = getApiConfig(env);
38
31
  if (!bffApiUrl) {
@@ -53,23 +46,12 @@ export async function getLBTCStats(
53
46
  `${bffApiUrl}/dune-api/query/getTotalLBTCUsers?partnerId=${partnerId || ''}`,
54
47
  );
55
48
 
56
- let apr = undefined;
57
- try {
58
- const { data: stakingStats } = await axios.get<StakingStatsResponse>(
59
- `${bffApiUrl}/lombard-sdk/staking-stats?partnerId=${partnerId || ''}&accountAddress=${accountAddress}&env=${env}`,
60
- );
61
- apr = stakingStats.apr;
62
- } catch (_err) {
63
- // NOOP
64
- }
65
-
66
49
  const stats: Stats = {
67
50
  price: BigNumber(data[0].price),
68
51
  supply: BigNumber(data[0].supply),
69
52
  tvl: BigNumber(data[0].tvl),
70
53
  holders: BigNumber(holders),
71
54
  historicalHolders: BigNumber(historicalHolders),
72
- apr: apr ? BigNumber(apr) : undefined,
73
55
  };
74
56
 
75
57
  return stats;
@@ -4,13 +4,13 @@ import { CodeBlock } from '../stories/components/CodeBlock';
4
4
  import useQuery from '../stories/hooks/useQuery';
5
5
  import { functionType, wagmiDecorator } from '../stories/components/decorators';
6
6
  import { ErrorBlock } from '../stories/components/error-block';
7
- import { getRewardsInfo } from './get-rewards-info';
7
+ import { getPositionsSummary } from './get-positions-summary';
8
8
  import { EXAMPLE_EVM_ADDRESS } from '../stories/constants';
9
9
  import { envSelector } from '../stories/arg-types';
10
10
  import { Env } from '@lombard.finance/sdk-common';
11
11
 
12
12
  const meta = {
13
- title: 'metrics/getRewardsInfo',
13
+ title: 'metrics/getPositionsSummary',
14
14
  component: StoryView,
15
15
  tags: ['autodocs'],
16
16
  decorators: [wagmiDecorator, functionType('api-get')],
@@ -25,11 +25,11 @@ export const WithParams: Story = {
25
25
  args: { account: EXAMPLE_EVM_ADDRESS, env: Env.stage },
26
26
  };
27
27
 
28
- type SignNetworkFeeProps = Parameters<typeof getRewardsInfo>[0];
28
+ type SignNetworkFeeProps = Parameters<typeof getPositionsSummary>[0];
29
29
 
30
30
  export function StoryView(props: SignNetworkFeeProps) {
31
31
  const request = async () => {
32
- return getRewardsInfo({
32
+ return getPositionsSummary({
33
33
  ...props,
34
34
  });
35
35
  };
@@ -46,7 +46,7 @@ export function StoryView(props: SignNetworkFeeProps) {
46
46
  onClick={refetch}
47
47
  disabled={isLoading}
48
48
  isLoading={isLoading}
49
- actionName={getRewardsInfo.name}
49
+ actionName={getPositionsSummary.name}
50
50
  />
51
51
 
52
52
  <ErrorBlock>{error}</ErrorBlock>
@@ -0,0 +1,134 @@
1
+ import axios from 'axios';
2
+ import BigNumber from 'bignumber.js';
3
+ import { Address } from 'viem';
4
+ import { getApiConfig } from '../common/api-config';
5
+ import { IEnvParam } from '../common/parameters';
6
+ import { Token } from '../tokens/token-addresses';
7
+
8
+ type PositionAsset = 'ASSET_LBTC' | 'ASSET_UNSPECIFIED';
9
+ type PositionType = 'BALANCE_TYPE_HOLDING' | 'BALANCE_TYPE_DEFI';
10
+
11
+ type Response = {
12
+ btc_price_usd: { price: number; timestamp: string };
13
+ btc_value: number;
14
+ btc_pnl: number;
15
+ snapshot: [
16
+ {
17
+ asset: PositionAsset;
18
+ type: PositionType;
19
+ balance: number;
20
+ pnl: number;
21
+ rate: number;
22
+ },
23
+ ];
24
+ last_updated: string;
25
+ };
26
+
27
+ function mapRewardAssetToToken(asset: PositionAsset) {
28
+ switch (asset) {
29
+ case 'ASSET_LBTC':
30
+ return Token.LBTC;
31
+ default:
32
+ return undefined;
33
+ }
34
+ }
35
+
36
+ export type PositionsSummary = {
37
+ /**
38
+ * The current BTC price in USD, along with the timestamp
39
+ * when the price was last fetched.
40
+ */
41
+ btcPrice: {
42
+ /** The price of 1 BTC in USD. */
43
+ price: BigNumber;
44
+ /** Timestamp of the price data. */
45
+ timestamp: Date;
46
+ };
47
+ /**
48
+ * Total value of all holdings, denominated in BTC.
49
+ */
50
+ btcValue: BigNumber;
51
+ /**
52
+ * Total profit or loss across all assets, represented in BTC.
53
+ */
54
+ btcPnl: BigNumber;
55
+ /**
56
+ * A detailed snapshot of position data used in PnL calculation.
57
+ */
58
+ snapshot: {
59
+ /**
60
+ * The token associated with this position (e.g., `Token.LBTC`).
61
+ * Can be `undefined` if unspecified.
62
+ */
63
+ token: Token | undefined;
64
+ /**
65
+ * The classification or source of the position.
66
+ */
67
+ type: PositionType;
68
+ /**
69
+ * The quantity of the token held.
70
+ */
71
+ balance: BigNumber;
72
+ /**
73
+ * The profit or loss for this specific position, in BTC.
74
+ */
75
+ pnl: BigNumber;
76
+ /**
77
+ * The conversion rate used to determine the BTC value of the balance.
78
+ * `balance * rate = BTC equivalent`
79
+ */
80
+ rate: BigNumber;
81
+ }[];
82
+ /**
83
+ * The timestamp when the PnL data was last updated.
84
+ */
85
+ lastUpdated: Date;
86
+ };
87
+
88
+ /** Retrieves the yield positions summary for the specified account address. */
89
+ export async function getPositionsSummary({
90
+ account,
91
+ env,
92
+ }: { account: Address } & IEnvParam) {
93
+ const { baseApiUrl } = getApiConfig(env);
94
+
95
+ const url = `${baseApiUrl}/api/v1/analytics/${account}/summary`;
96
+ const { data } = await axios.get<Response>(url);
97
+
98
+ const info: PositionsSummary = {
99
+ btcPrice: {
100
+ price: BigNumber(data.btc_price_usd.price || 0),
101
+ timestamp: new Date(data.btc_price_usd.timestamp),
102
+ },
103
+ btcValue: BigNumber(data.btc_value || 0),
104
+ btcPnl: BigNumber(data.btc_pnl || 0),
105
+ snapshot: data.snapshot.map(ds => ({
106
+ token: mapRewardAssetToToken(ds.asset),
107
+ type: ds.type,
108
+ balance: BigNumber(ds.balance || 0),
109
+ pnl: BigNumber(ds.pnl || 0),
110
+ rate: BigNumber(ds.rate || 0),
111
+ })),
112
+ lastUpdated: new Date(data.last_updated),
113
+ };
114
+
115
+ return info;
116
+ }
117
+
118
+ // Response example:
119
+ // url: https://bft-dev.stage.lombard.finance/api/v1/analytics/0x2513196b4fD01Ed5888d1dB49AB9a42208E9fF90/summary
120
+ // {
121
+ // btc_price_usd: { price: 118395.552997, timestamp: '2025-07-23T11:01:59Z' },
122
+ // btc_value: 0.0003895271690089053,
123
+ // btc_pnl: 8.716900890527854e-8,
124
+ // snapshot: [
125
+ // {
126
+ // asset: 'ASSET_LBTC',
127
+ // type: 'BALANCE_TYPE_HOLDING',
128
+ // balance: 0.00038944,
129
+ // pnl: 8.716900890527854e-8,
130
+ // rate: 1.0002238316785776,
131
+ // },
132
+ // ],
133
+ // last_updated: '2025-07-23T11:38:52.516364988Z',
134
+ // }
@@ -1,72 +0,0 @@
1
- import axios from 'axios';
2
- import BigNumber from 'bignumber.js';
3
- import { Address } from 'viem';
4
- import { getApiConfig } from '../common/api-config';
5
- import { IEnvParam } from '../common/parameters';
6
- import { BlockchainIdentifier } from '../common/blockchain-identifier';
7
-
8
- type Response = {
9
- btc_price_usd: { price: number; timestamp: string };
10
- staked_balance: number;
11
- rewards: number;
12
- chain_breakdown: {
13
- staked_balance: number;
14
- rewards: number;
15
- chain: BlockchainIdentifier;
16
- }[];
17
- last_updated: string;
18
- };
19
-
20
- /**
21
- * Gets the rewards info acquired by provided account address
22
- *
23
- * @experimental This function is not ready to be used in prod environment and will result with static and dummy data. Please do not rely on the data it returns.
24
- */
25
- export async function getRewardsInfo({
26
- account,
27
- env,
28
- }: { account: Address } & IEnvParam) {
29
- const { baseApiUrl } = getApiConfig(env);
30
-
31
- const url = `${baseApiUrl}/api/v1/accounts/${account}/summary`;
32
- const { data } = await axios.get<Response>(url);
33
-
34
- const info = {
35
- btcPrice: {
36
- price: BigNumber(data.btc_price_usd.price || 0),
37
- timestamp: new Date(data.btc_price_usd.timestamp),
38
- },
39
- stakedBalance: BigNumber(data.staked_balance || 0),
40
- totalRewards: BigNumber(data.rewards || 0),
41
- chainBreakdown: data.chain_breakdown?.map(cd => ({
42
- stakedBalance: BigNumber(cd.staked_balance || 0),
43
- rewards: BigNumber(cd.rewards || 0),
44
- chain: cd.chain,
45
- })),
46
- lastUpdated: new Date(data.last_updated),
47
- };
48
-
49
- return info;
50
- }
51
-
52
- // Response example:
53
- // url: https://bft-dev.stage.lombard.finance/api/v1/accounts/0x2513196b4fD01Ed5888d1dB49AB9a42208E9fF90/summary
54
- //
55
- // {
56
- // btc_price_usd: { price: 118597.502311, timestamp: '2025-07-22T14:17:23Z' },
57
- // staked_balance: 0.00038944,
58
- // rewards: 8.716900890527854e-8,
59
- // chain_breakdown: [
60
- // {
61
- // staked_balance: 0.00018844,
62
- // rewards: 4.217884151117165e-8,
63
- // chain: 'DESTINATION_BLOCKCHAIN_BSC',
64
- // },
65
- // {
66
- // staked_balance: 0.000201,
67
- // rewards: 4.4990167394106886e-8,
68
- // chain: 'DESTINATION_BLOCKCHAIN_ETHEREUM',
69
- // },
70
- // ],
71
- // last_updated: '2025-07-22T15:07:20.502595933Z',
72
- // }