@reyaxyz/common 0.362.1 → 0.363.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.
Files changed (104) hide show
  1. package/README.md +1 -1
  2. package/dist/commands/exposure/command.js +8 -22
  3. package/dist/commands/exposure/command.js.map +1 -1
  4. package/dist/incentives-api-types.js.map +1 -1
  5. package/dist/services/getNativeToken.js +1 -0
  6. package/dist/services/getNativeToken.js.map +1 -1
  7. package/dist/services/getSocketAddresses.js +1 -0
  8. package/dist/services/getSocketAddresses.js.map +1 -1
  9. package/dist/trading-api-types.js.map +1 -1
  10. package/dist/transactions/abis/Errors.json +1638 -34
  11. package/dist/transactions/abis/OrdersGateway.json +729 -123
  12. package/dist/transactions/abis/PassivePerpProxy.json +542 -0
  13. package/dist/transactions/buildMulticallTx.js.map +1 -1
  14. package/dist/transactions/consts.js +1 -2
  15. package/dist/transactions/consts.js.map +1 -1
  16. package/dist/transactions/contractAddresses.js +45 -5
  17. package/dist/transactions/contractAddresses.js.map +1 -1
  18. package/dist/transactions/sign.js +237 -111
  19. package/dist/transactions/sign.js.map +1 -1
  20. package/dist/types/commands/exposure/command.d.ts +8 -7
  21. package/dist/types/commands/exposure/command.d.ts.map +1 -1
  22. package/dist/types/incentives-api-types.d.ts +61 -5
  23. package/dist/types/incentives-api-types.d.ts.map +1 -1
  24. package/dist/types/services/getNativeToken.d.ts.map +1 -1
  25. package/dist/types/services/getSocketAddresses.d.ts.map +1 -1
  26. package/dist/types/trading-api-types.d.ts +200 -32
  27. package/dist/types/trading-api-types.d.ts.map +1 -1
  28. package/dist/types/transactions/buildMulticallTx.d.ts +1 -0
  29. package/dist/types/transactions/buildMulticallTx.d.ts.map +1 -1
  30. package/dist/types/transactions/consts.d.ts +0 -1
  31. package/dist/types/transactions/consts.d.ts.map +1 -1
  32. package/dist/types/transactions/contractAddresses.d.ts +0 -1
  33. package/dist/types/transactions/contractAddresses.d.ts.map +1 -1
  34. package/dist/types/transactions/sign.d.ts +113 -9
  35. package/dist/types/transactions/sign.d.ts.map +1 -1
  36. package/dist/types/types.d.ts +61 -65
  37. package/dist/types/types.d.ts.map +1 -1
  38. package/dist/types/utils/calculate.d.ts.map +1 -1
  39. package/dist/types/utils/consts.d.ts +2 -2
  40. package/dist/types/utils/consts.d.ts.map +1 -1
  41. package/dist/types/utils/error-sanitizer.d.ts +15 -0
  42. package/dist/types/utils/error-sanitizer.d.ts.map +1 -0
  43. package/dist/types/utils/index.d.ts +3 -0
  44. package/dist/types/utils/index.d.ts.map +1 -1
  45. package/dist/types/utils/network.d.ts.map +1 -1
  46. package/dist/types/utils/number.d.ts +5 -0
  47. package/dist/types/utils/number.d.ts.map +1 -1
  48. package/dist/types/utils/realized-balance.d.ts +54 -0
  49. package/dist/types/utils/realized-balance.d.ts.map +1 -0
  50. package/dist/types/utils/throttled-error.d.ts +42 -0
  51. package/dist/types/utils/throttled-error.d.ts.map +1 -0
  52. package/dist/types/utils/token/normalize.d.ts +2 -1
  53. package/dist/types/utils/token/normalize.d.ts.map +1 -1
  54. package/dist/types/utils/token/token-info-getters.d.ts.map +1 -1
  55. package/dist/types/utils/token/token-info.d.ts.map +1 -1
  56. package/dist/types.js +25 -11
  57. package/dist/types.js.map +1 -1
  58. package/dist/utils/calculate.js +18 -9
  59. package/dist/utils/calculate.js.map +1 -1
  60. package/dist/utils/consts.js +2 -7
  61. package/dist/utils/consts.js.map +1 -1
  62. package/dist/utils/error-sanitizer.js +135 -0
  63. package/dist/utils/error-sanitizer.js.map +1 -0
  64. package/dist/utils/index.js +3 -0
  65. package/dist/utils/index.js.map +1 -1
  66. package/dist/utils/network.js +4 -0
  67. package/dist/utils/network.js.map +1 -1
  68. package/dist/utils/number.js +96 -1
  69. package/dist/utils/number.js.map +1 -1
  70. package/dist/utils/realized-balance.js +126 -0
  71. package/dist/utils/realized-balance.js.map +1 -0
  72. package/dist/utils/throttled-error.js +60 -0
  73. package/dist/utils/throttled-error.js.map +1 -0
  74. package/dist/utils/token/normalize.js +2 -2
  75. package/dist/utils/token/normalize.js.map +1 -1
  76. package/dist/utils/token/token-info-getters.js +80 -5
  77. package/dist/utils/token/token-info-getters.js.map +1 -1
  78. package/dist/utils/token/token-info.js +7 -0
  79. package/dist/utils/token/token-info.js.map +1 -1
  80. package/package.json +3 -3
  81. package/src/commands/exposure/command.ts +8 -38
  82. package/src/incentives-api-types.ts +60 -5
  83. package/src/services/getNativeToken.ts +1 -0
  84. package/src/services/getSocketAddresses.ts +1 -0
  85. package/src/trading-api-types.ts +258 -39
  86. package/src/transactions/abis/Errors.json +5478 -3874
  87. package/src/transactions/abis/OrdersGateway.json +730 -124
  88. package/src/transactions/abis/PassivePerpProxy.json +542 -0
  89. package/src/transactions/buildMulticallTx.ts +4 -0
  90. package/src/transactions/consts.ts +0 -1
  91. package/src/transactions/contractAddresses.ts +42 -7
  92. package/src/transactions/sign.ts +306 -150
  93. package/src/types.ts +98 -83
  94. package/src/utils/calculate.ts +21 -8
  95. package/src/utils/consts.ts +4 -16
  96. package/src/utils/error-sanitizer.ts +137 -0
  97. package/src/utils/index.ts +3 -0
  98. package/src/utils/network.ts +4 -0
  99. package/src/utils/number.ts +110 -0
  100. package/src/utils/realized-balance.ts +163 -0
  101. package/src/utils/throttled-error.ts +85 -0
  102. package/src/utils/token/normalize.ts +6 -1
  103. package/src/utils/token/token-info-getters.ts +104 -6
  104. package/src/utils/token/token-info.ts +42 -0
@@ -0,0 +1,163 @@
1
+ import BigNumber from 'bignumber.js';
2
+
3
+ /** Raw E18 position values, from either Prisma or replication. */
4
+ export type RealizedBalancePosition = {
5
+ market_id: { toString(): string };
6
+ base: { toString(): string } | null;
7
+ realized_pnl: { toString(): string } | null;
8
+ funding_value: { toString(): string } | null;
9
+ base_multiplier: { toString(): string } | null;
10
+ adl_unwind_price: { toString(): string } | null;
11
+ last_price: { toString(): string } | null;
12
+ /** Block the stored trackers were written at; lets stale market trackers be ignored. */
13
+ block_number?: { toString(): string } | null;
14
+ };
15
+
16
+ export type RealizedBalanceTrackers = {
17
+ longTrackersFundingValue: string;
18
+ shortTrackersFundingValue: string;
19
+ longTrackersBaseMultiplier: string;
20
+ shortTrackersBaseMultiplier: string;
21
+ longTrackersAdlUnwindPrice: string;
22
+ shortTrackersAdlUnwindPrice: string;
23
+ /** Block the market trackers were observed at (optional; enables the staleness guard). */
24
+ blockNumber?: string | null;
25
+ };
26
+
27
+ /** Structured cause for service metrics; calculation still fails closed. */
28
+ export class SettlementTrackerError extends Error {
29
+ constructor(
30
+ public readonly marketId: string,
31
+ public readonly reason: 'missing' | 'inconsistent',
32
+ ) {
33
+ super(
34
+ reason === 'missing'
35
+ ? `Missing market trackers for ${marketId}`
36
+ : `Inconsistent ADL trackers for ${marketId}`,
37
+ );
38
+ // common targets ES5; restore Error subclass identity after downleveling.
39
+ Object.setPrototypeOf(this, new.target.prototype);
40
+ this.name = 'SettlementTrackerError';
41
+ }
42
+ }
43
+
44
+ const WAD = new BigNumber('1000000000000000000');
45
+ const integer = (value: { toString(): string } | null, field: string) => {
46
+ const result = new BigNumber(value?.toString() ?? NaN);
47
+ if (!result.isInteger()) throw new Error(`Missing or invalid ${field}`);
48
+ return result;
49
+ };
50
+ const optionalBlock = (value: { toString(): string } | null | undefined) => {
51
+ if (value === null || value === undefined) return undefined;
52
+ const result = new BigNumber(value.toString());
53
+ return result.isInteger() ? result : undefined;
54
+ };
55
+ const mulWad = (a: BigNumber, b: BigNumber) =>
56
+ a.times(b).dividedToIntegerBy(WAD);
57
+ const divWad = (a: BigNumber, b: BigNumber) =>
58
+ a.times(WAD).dividedToIntegerBy(b);
59
+
60
+ /** Mirrors perpOB updatePerpPosition, including PRBMath truncation at each step. */
61
+ export function calculateSettledPositionPnl(
62
+ position: RealizedBalancePosition,
63
+ trackers: RealizedBalanceTrackers | undefined,
64
+ onGuarded?: () => void,
65
+ ): BigNumber {
66
+ const base = integer(position.base, 'position base');
67
+ const realized = integer(position.realized_pnl, 'realized PnL');
68
+ if (base.isZero()) return realized;
69
+ if (!trackers)
70
+ throw new SettlementTrackerError(position.market_id.toString(), 'missing');
71
+
72
+ const long = base.isPositive();
73
+ const funding = integer(
74
+ long
75
+ ? trackers.longTrackersFundingValue
76
+ : trackers.shortTrackersFundingValue,
77
+ 'market funding',
78
+ );
79
+ const multiplier = integer(
80
+ long
81
+ ? trackers.longTrackersBaseMultiplier
82
+ : trackers.shortTrackersBaseMultiplier,
83
+ 'market multiplier',
84
+ );
85
+ const unwind = integer(
86
+ long
87
+ ? trackers.longTrackersAdlUnwindPrice
88
+ : trackers.shortTrackersAdlUnwindPrice,
89
+ 'market unwind price',
90
+ );
91
+ const oldMultiplier = integer(
92
+ position.base_multiplier,
93
+ 'position multiplier',
94
+ );
95
+ const oldUnwind = integer(position.adl_unwind_price, 'position unwind price');
96
+ const oldFunding = integer(position.funding_value, 'position funding');
97
+ if (
98
+ funding.eq(oldFunding) &&
99
+ multiplier.eq(oldMultiplier) &&
100
+ unwind.eq(oldUnwind)
101
+ )
102
+ return realized;
103
+
104
+ // Market trackers older than the position's own snapshot carry no new
105
+ // cashflow: the stored realized PnL already settled everything up to the
106
+ // position's block. Off-chain tracker feeds can lag the position stream, so
107
+ // treat that window as "nothing accrued" instead of projecting a delta
108
+ // backwards (wrong-sign funding, or an ADL guard failure below).
109
+ const positionBlock = optionalBlock(position.block_number);
110
+ const trackerBlock = optionalBlock(trackers.blockNumber);
111
+ if (positionBlock && trackerBlock && positionBlock.gt(trackerBlock)) {
112
+ onGuarded?.();
113
+ return realized;
114
+ }
115
+
116
+ if (
117
+ oldMultiplier.lte(0) ||
118
+ multiplier.lt(0) ||
119
+ multiplier.gt(oldMultiplier) ||
120
+ unwind.lt(oldUnwind)
121
+ ) {
122
+ throw new SettlementTrackerError(
123
+ position.market_id.toString(),
124
+ 'inconsistent',
125
+ );
126
+ }
127
+ const fundingCashflow = mulWad(
128
+ divWad(funding.minus(oldFunding), oldMultiplier),
129
+ base.negated(),
130
+ );
131
+ const unwindDelta = divWad(unwind.minus(oldUnwind), oldMultiplier);
132
+ const initialPrice = mulWad(
133
+ WAD.minus(divWad(multiplier, oldMultiplier)),
134
+ integer(position.last_price, 'position price'),
135
+ );
136
+ const adlCashflow = mulWad(base, unwindDelta.minus(initialPrice));
137
+ return realized.plus(fundingCashflow).plus(adlCashflow);
138
+ }
139
+
140
+ /**
141
+ * Returns raw E18 PnL aligned to collateral units. The instrument floors EACH
142
+ * market's PnL to quote-token precision before Core aggregates collateral info.
143
+ * Funding is the stored market tracker delta; do not extrapolate it with time.
144
+ */
145
+ export function calculateSettledAccountPnl(
146
+ positions: RealizedBalancePosition[],
147
+ trackers: Partial<Record<string, RealizedBalanceTrackers>>,
148
+ collateralDecimals: number,
149
+ onGuarded?: () => void,
150
+ ): BigNumber {
151
+ return positions.reduce((sum, position) => {
152
+ const pnl = calculateSettledPositionPnl(
153
+ position,
154
+ trackers[position.market_id.toString()],
155
+ onGuarded,
156
+ );
157
+ const rounded = pnl
158
+ .shiftedBy(collateralDecimals - 18)
159
+ .integerValue(BigNumber.ROUND_FLOOR)
160
+ .shiftedBy(18 - collateralDecimals);
161
+ return sum.plus(rounded);
162
+ }, new BigNumber(0));
163
+ }
@@ -0,0 +1,85 @@
1
+ export interface ThrottleState {
2
+ lastEmitMs: number;
3
+ suppressed: number;
4
+ }
5
+
6
+ /**
7
+ * Sustained-gate state: a sliding window of recent occurrence timestamps
8
+ * (len-capped at `threshold`), plus the last emit time and the count dropped
9
+ * since it (folded into the next emitted line).
10
+ */
11
+ export interface SustainedState {
12
+ times: number[];
13
+ lastEmitMs: number | null;
14
+ suppressed: number;
15
+ }
16
+
17
+ /**
18
+ * Pure throttle decision (`nowMs` injected for testability). Returns the next
19
+ * state and `emit`: the suppressed-since-previous count if the line should be
20
+ * emitted now (the counter resets), or `null` to suppress (incrementing the
21
+ * dropped counter). The first call at a key (no prior state) always emits.
22
+ */
23
+ export function throttleDecision(
24
+ prev: ThrottleState | undefined,
25
+ nowMs: number,
26
+ windowMs: number,
27
+ ): { next: ThrottleState; emit: number | null } {
28
+ if (prev && nowMs - prev.lastEmitMs < windowMs) {
29
+ return {
30
+ next: { lastEmitMs: prev.lastEmitMs, suppressed: prev.suppressed + 1 },
31
+ emit: null,
32
+ };
33
+ }
34
+ return {
35
+ next: { lastEmitMs: nowMs, suppressed: 0 },
36
+ emit: prev?.suppressed ?? 0,
37
+ };
38
+ }
39
+
40
+ /**
41
+ * Pure sustained-gate + throttle decision (`nowMs` injected for testability).
42
+ * Occurrences outside the sliding window are dropped before the current
43
+ * occurrence is recorded. The timestamp deque is capped at `threshold`, since
44
+ * older entries cannot affect the next decision once the threshold is met.
45
+ *
46
+ * Emits only when at least `threshold` occurrences fall within the window and
47
+ * at least `windowMs` has elapsed since the previous emit. A gate-open
48
+ * occurrence blocked by that re-emission throttle increments `suppressed`.
49
+ */
50
+ export function sustainedDecision(
51
+ prev: SustainedState | undefined,
52
+ nowMs: number,
53
+ windowMs: number,
54
+ threshold: number,
55
+ ): {
56
+ next: SustainedState;
57
+ emit: { occurrences: number; suppressed: number } | null;
58
+ } {
59
+ const times = (prev?.times ?? []).filter((t) => nowMs - t < windowMs);
60
+ times.push(nowMs);
61
+ while (times.length > threshold) times.shift();
62
+
63
+ const prevLastEmitMs = prev?.lastEmitMs ?? null;
64
+ const prevSuppressed = prev?.suppressed ?? 0;
65
+
66
+ const gateOpen = times.length >= threshold;
67
+ const throttleElapsed =
68
+ prevLastEmitMs === null || nowMs - prevLastEmitMs >= windowMs;
69
+
70
+ if (gateOpen && throttleElapsed) {
71
+ return {
72
+ next: { times, lastEmitMs: nowMs, suppressed: 0 },
73
+ emit: { occurrences: times.length, suppressed: prevSuppressed },
74
+ };
75
+ }
76
+
77
+ return {
78
+ next: {
79
+ times,
80
+ lastEmitMs: prevLastEmitMs,
81
+ suppressed: gateOpen ? prevSuppressed + 1 : prevSuppressed,
82
+ },
83
+ emit: null,
84
+ };
85
+ }
@@ -1,4 +1,5 @@
1
1
  import { TradingApi } from '../../trading-api-types';
2
+ import { MoneyInOutChainId, ReyaChainId } from '../../types';
2
3
  import { getTokenInfoByAddress } from './token-info-getters';
3
4
 
4
5
  export const normalizeDecimals = (
@@ -16,11 +17,15 @@ export const normalizeDecimals = (
16
17
 
17
18
  export const normalizeAccountBalance = (
18
19
  accountBalance: TradingApi['wallet/:address/accounts/balances']['response'][0],
20
+ chainId?: ReyaChainId | MoneyInOutChainId,
19
21
  ) => {
20
22
  if (!accountBalance.collateral) {
21
23
  return accountBalance;
22
24
  }
23
- const decimals = getTokenInfoByAddress(accountBalance.collateral).decimals;
25
+ const decimals = getTokenInfoByAddress(
26
+ accountBalance.collateral,
27
+ chainId,
28
+ ).decimals;
24
29
  return {
25
30
  ...accountBalance,
26
31
  balance: normalizeDecimals(accountBalance.balance, decimals),
@@ -8,6 +8,94 @@ import {
8
8
  } from '../../types';
9
9
  import { convertToAddress } from './utils';
10
10
 
11
+ const LOCAL_ADDRESS_PATTERN = /^0x[a-fA-F0-9]{40}$/;
12
+
13
+ const localAddressOverride = (envName: string, fallback: Address): Address => {
14
+ const rawAddress = process.env[envName]?.trim();
15
+ if (!rawAddress) {
16
+ return fallback;
17
+ }
18
+
19
+ if (!LOCAL_ADDRESS_PATTERN.test(rawAddress)) {
20
+ throw new Error(`Invalid ${envName} address override: ${rawAddress}`);
21
+ }
22
+
23
+ return rawAddress.toLowerCase() as Address;
24
+ };
25
+
26
+ /**
27
+ * The Reya chains whose token addresses may be overridden from the
28
+ * environment. An ALLOWLIST on purpose: this function also accepts
29
+ * MoneyInOutChainId, and TOKEN_INFO carries entries for external chains
30
+ * (ethereum, op, polygon, arbitrum, base) whose USDC/WETH names collide with
31
+ * the ones overridden below. A "not mainnet" test would quietly rewrite those
32
+ * external addresses from Reya-local env vars; an allowlist cannot, and a new
33
+ * money-in/out chain cannot opt itself in by accident.
34
+ *
35
+ * reyaCronos is here because devnet1 shares that chain id while running its
36
+ * OWN passive pool and sRUSD (2026-08-22), publishing SRUSD_PROXY_ADDRESS in
37
+ * its api values. Gated on reyaLocal alone it never reached this path, so
38
+ * getTokenInfoByAddress threw "no token info found" for devnet's own sRUSD,
39
+ * which broke /v2/wallet/:address/accountBalances -- the RLP balance never
40
+ * appeared after staking rUSD. Each override still falls back to the compiled
41
+ * address when its env var is unset, so cronos itself is a no-op.
42
+ *
43
+ * Same root cause and same fix as the asset map in common-backend (#2903);
44
+ * these two must stay in step.
45
+ */
46
+ const REYA_CHAINS_WITH_ADDRESS_OVERRIDES: ReadonlySet<ReyaChainId> = new Set([
47
+ ReyaChainId.reyaLocal,
48
+ ReyaChainId.reyaCronos,
49
+ ]);
50
+
51
+ const withLocalAddressOverrides = (tokenInfos: TokenInfo[]): TokenInfo[] =>
52
+ tokenInfos.map((tokenInfo) => {
53
+ switch (tokenInfo.name) {
54
+ case 'RUSD':
55
+ return {
56
+ ...tokenInfo,
57
+ address: localAddressOverride(
58
+ 'RUSD_COLLATERAL_ADDRESS',
59
+ tokenInfo.address,
60
+ ),
61
+ };
62
+ case 'WETH':
63
+ return {
64
+ ...tokenInfo,
65
+ address: localAddressOverride(
66
+ 'LOCAL_ETH_ASSET_ADDRESS',
67
+ tokenInfo.address,
68
+ ),
69
+ };
70
+ case 'WBTC':
71
+ return {
72
+ ...tokenInfo,
73
+ address: localAddressOverride(
74
+ 'LOCAL_BTC_ASSET_ADDRESS',
75
+ tokenInfo.address,
76
+ ),
77
+ };
78
+ case 'SRUSD':
79
+ return {
80
+ ...tokenInfo,
81
+ address: localAddressOverride(
82
+ 'SRUSD_PROXY_ADDRESS',
83
+ tokenInfo.address,
84
+ ),
85
+ };
86
+ case 'USDC':
87
+ return {
88
+ ...tokenInfo,
89
+ address: localAddressOverride(
90
+ 'LOCAL_USDC_ASSET_ADDRESS',
91
+ tokenInfo.address,
92
+ ),
93
+ };
94
+ default:
95
+ return tokenInfo;
96
+ }
97
+ });
98
+
11
99
  export const getTokenInfoByAddress = (
12
100
  tokenAddressParam: Address | string,
13
101
  chainId?: ReyaChainId | MoneyInOutChainId,
@@ -18,7 +106,7 @@ export const getTokenInfoByAddress = (
18
106
  : tokenAddressParam;
19
107
 
20
108
  if (chainId) {
21
- const tokenInfo = TOKEN_INFO[chainId].find(
109
+ const tokenInfo = getTokenInfosByChain(chainId).find(
22
110
  (tokenInfo) => tokenInfo.address === tokenAddress,
23
111
  );
24
112
  if (!tokenInfo) {
@@ -29,8 +117,15 @@ export const getTokenInfoByAddress = (
29
117
  return tokenInfo;
30
118
  } else {
31
119
  for (const chainId in TOKEN_INFO) {
32
- const tokenInfos =
33
- TOKEN_INFO[chainId as unknown as keyof typeof TOKEN_INFO];
120
+ // getTokenInfosByChain, NOT raw TOKEN_INFO: the address overrides live
121
+ // in that function, so reading the table directly here made this branch
122
+ // blind to any deployment running its own token. devnet1's sRUSD
123
+ // resolved on the chainId-passing branch above and threw here --
124
+ // "no token info found [token address 0x8a04...]", with no chainId in
125
+ // the message, which is what distinguishes the two call sites.
126
+ const tokenInfos = getTokenInfosByChain(
127
+ Number(chainId) as ReyaChainId | MoneyInOutChainId,
128
+ );
34
129
  const tokenInfo = tokenInfos.find(
35
130
  (tokenInfo) => tokenInfo.address === tokenAddress,
36
131
  );
@@ -48,7 +143,7 @@ export const getTokenInfoByName = (
48
143
  tokenName: TokenName,
49
144
  chainId: ReyaChainId | MoneyInOutChainId,
50
145
  ): TokenInfo => {
51
- const tokenInfo = TOKEN_INFO[chainId].find(
146
+ const tokenInfo = getTokenInfosByChain(chainId).find(
52
147
  (tokenInfo) => tokenInfo.name === tokenName,
53
148
  );
54
149
 
@@ -64,13 +159,16 @@ export const getTokenInfoByName = (
64
159
  export const getTokenInfosByChain = (
65
160
  chainId: ReyaChainId | MoneyInOutChainId,
66
161
  ): TokenInfo[] => {
67
- return TOKEN_INFO[chainId];
162
+ const tokenInfos = TOKEN_INFO[chainId];
163
+ return REYA_CHAINS_WITH_ADDRESS_OVERRIDES.has(chainId as ReyaChainId)
164
+ ? withLocalAddressOverrides(tokenInfos)
165
+ : tokenInfos;
68
166
  };
69
167
 
70
168
  export const getRUSDUnderlyingTokenInfo = (
71
169
  chainId: ReyaChainId | MoneyInOutChainId,
72
170
  ): TokenInfo => {
73
- const tokenInfo = TOKEN_INFO[chainId].find(
171
+ const tokenInfo = getTokenInfosByChain(chainId).find(
74
172
  (tokenInfo) => tokenInfo.isRUSDUnderlying === true,
75
173
  );
76
174
 
@@ -537,6 +537,48 @@ export const TOKEN_INFO: Record<ReyaChainId | MoneyInOutChainId, TokenInfo[]> =
537
537
  minTransferAmount: 1,
538
538
  },
539
539
  ],
540
+ [ReyaChainId.reyaLocal]: [
541
+ {
542
+ name: 'WBTC',
543
+ address: '0x459374f3f3e92728bca838dfa8c95e706fe67e8a',
544
+ decimals: 8,
545
+ isRUSDUnderlying: false,
546
+ ...defaultTokenThresholds,
547
+ },
548
+ {
549
+ name: 'RUSD',
550
+ address: '0x9de724e7b3facf87ce39465d3d712717182e3e55',
551
+ decimals: 6,
552
+ isRUSDUnderlying: false,
553
+ ...defaultTokenThresholds,
554
+ },
555
+ {
556
+ name: 'USDC',
557
+ address: '0xfa27c7c6051344263533cc365274d9569b0272a8',
558
+ decimals: 6,
559
+ isRUSDUnderlying: true,
560
+ ...defaultTokenThresholds,
561
+ },
562
+ {
563
+ name: 'WETH',
564
+ address: '0x2cf56315acc7e791b1a0135c09d8d5c8dbcd2f14',
565
+ decimals: 18,
566
+ isRUSDUnderlying: false,
567
+ ...defaultTokenThresholds,
568
+ minDepositAmount: 0.01,
569
+ minWithdrawAmount: 0.01,
570
+ minTransferAmount: 0.01,
571
+ },
572
+ {
573
+ name: 'SRUSD',
574
+ address: '0xb9f531a54fc0e9adca1b931d9533b4e49bb2fad6',
575
+ decimals: 30,
576
+ isRUSDUnderlying: false,
577
+ whitelistedWalletOnly: false,
578
+ isPoolToken: true,
579
+ ...defaultTokenThresholds,
580
+ },
581
+ ],
540
582
  [MoneyInOutChainId.arbitrumSepolia]: [
541
583
  {
542
584
  name: 'USDC',