@kehtus/proportion-sdk 0.4.2 → 1.1.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 (96) hide show
  1. package/LICENSE +21 -21
  2. package/dist/abi/challengeAccount.d.ts +1855 -0
  3. package/dist/abi/challengeAccount.d.ts.map +1 -0
  4. package/dist/abi/challengeAccount.js +2365 -0
  5. package/dist/abi/challengeAccount.js.map +1 -0
  6. package/dist/abi/challengeFactory.d.ts +1351 -0
  7. package/dist/abi/challengeFactory.d.ts.map +1 -0
  8. package/dist/abi/challengeFactory.js +1727 -0
  9. package/dist/abi/challengeFactory.js.map +1 -0
  10. package/dist/abi/challengeVault.d.ts +1392 -0
  11. package/dist/abi/challengeVault.d.ts.map +1 -0
  12. package/dist/abi/challengeVault.js +1793 -0
  13. package/dist/abi/challengeVault.js.map +1 -0
  14. package/dist/abi/factory.d.ts +4 -0
  15. package/dist/abi/factory.d.ts.map +1 -1
  16. package/dist/abi/factory.js +5 -0
  17. package/dist/abi/factory.js.map +1 -1
  18. package/dist/abi/fundedAccount.d.ts +49 -20
  19. package/dist/abi/fundedAccount.d.ts.map +1 -1
  20. package/dist/abi/fundedAccount.js +62 -26
  21. package/dist/abi/fundedAccount.js.map +1 -1
  22. package/dist/abi/mainVault.d.ts +409 -64
  23. package/dist/abi/mainVault.d.ts.map +1 -1
  24. package/dist/abi/mainVault.js +523 -75
  25. package/dist/abi/mainVault.js.map +1 -1
  26. package/dist/abi/priceOracle.d.ts +497 -0
  27. package/dist/abi/priceOracle.d.ts.map +1 -0
  28. package/dist/abi/priceOracle.js +644 -0
  29. package/dist/abi/priceOracle.js.map +1 -0
  30. package/dist/account.d.ts.map +1 -1
  31. package/dist/account.js +6 -0
  32. package/dist/account.js.map +1 -1
  33. package/dist/challenge/account.d.ts +95 -0
  34. package/dist/challenge/account.d.ts.map +1 -0
  35. package/dist/challenge/account.js +375 -0
  36. package/dist/challenge/account.js.map +1 -0
  37. package/dist/challenge/api.d.ts +49 -0
  38. package/dist/challenge/api.d.ts.map +1 -0
  39. package/dist/challenge/api.js +173 -0
  40. package/dist/challenge/api.js.map +1 -0
  41. package/dist/challenge/factory.d.ts +151 -0
  42. package/dist/challenge/factory.d.ts.map +1 -0
  43. package/dist/challenge/factory.js +355 -0
  44. package/dist/challenge/factory.js.map +1 -0
  45. package/dist/challenge/intents.d.ts +137 -0
  46. package/dist/challenge/intents.d.ts.map +1 -0
  47. package/dist/challenge/intents.js +218 -0
  48. package/dist/challenge/intents.js.map +1 -0
  49. package/dist/challenge/oracle.d.ts +50 -0
  50. package/dist/challenge/oracle.d.ts.map +1 -0
  51. package/dist/challenge/oracle.js +117 -0
  52. package/dist/challenge/oracle.js.map +1 -0
  53. package/dist/challenge/types.d.ts +652 -0
  54. package/dist/challenge/types.d.ts.map +1 -0
  55. package/dist/challenge/types.js +64 -0
  56. package/dist/challenge/types.js.map +1 -0
  57. package/dist/challenge/vault.d.ts +87 -0
  58. package/dist/challenge/vault.d.ts.map +1 -0
  59. package/dist/challenge/vault.js +299 -0
  60. package/dist/challenge/vault.js.map +1 -0
  61. package/dist/constants.d.ts +14 -4
  62. package/dist/constants.d.ts.map +1 -1
  63. package/dist/constants.js +23 -4
  64. package/dist/constants.js.map +1 -1
  65. package/dist/factory.d.ts +1 -1
  66. package/dist/factory.d.ts.map +1 -1
  67. package/dist/factory.js +12 -0
  68. package/dist/factory.js.map +1 -1
  69. package/dist/forwarder.d.ts +58 -0
  70. package/dist/forwarder.d.ts.map +1 -0
  71. package/dist/forwarder.js +145 -0
  72. package/dist/forwarder.js.map +1 -0
  73. package/dist/index.d.ts +13 -0
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +14 -0
  76. package/dist/index.js.map +1 -1
  77. package/dist/indexer.d.ts +52 -0
  78. package/dist/indexer.d.ts.map +1 -1
  79. package/dist/indexer.js +349 -145
  80. package/dist/indexer.js.map +1 -1
  81. package/dist/sdk.d.ts +18 -1
  82. package/dist/sdk.d.ts.map +1 -1
  83. package/dist/sdk.js +85 -32
  84. package/dist/sdk.js.map +1 -1
  85. package/dist/types.d.ts +54 -0
  86. package/dist/types.d.ts.map +1 -1
  87. package/dist/types.js.map +1 -1
  88. package/dist/utils.d.ts +35 -2
  89. package/dist/utils.d.ts.map +1 -1
  90. package/dist/utils.js +86 -7
  91. package/dist/utils.js.map +1 -1
  92. package/dist/vault.d.ts +44 -5
  93. package/dist/vault.d.ts.map +1 -1
  94. package/dist/vault.js +138 -12
  95. package/dist/vault.js.map +1 -1
  96. package/package.json +2 -2
package/dist/indexer.js CHANGED
@@ -21,8 +21,24 @@ export class IndexerModule {
21
21
  static MAIN_VAULT_CONFIG_FIELDS = `id vaultAddress factoryAddress owner pendingOwner relayer paused protocolFeeReceiver feeMultiplier subscriptionFeeMultiplier dailyDdDiscountBps minBuilderShares builderLeverage protocolFeeBps minAccountSize maxAccountSize minDrawdownBps maxDrawdownBps maxUtilizationBps maxSingleAccountBps hypeForSpot maxCap createdAt updatedAt`;
22
22
  static FACTORY_CONFIG_FIELDS = `id factoryAddress vaultAddress owner pendingOwner createdAt updatedAt`;
23
23
  static CONFIG_CHANGE_FIELDS = `id contractAddress contractType field oldValue newValue blockNumber timestamp txHash`;
24
- static VAULT_DAY_DATA_FIELDS = `id date dayNumber evmBalance totalAllocated totalAssets totalShares sharePrice dailyDeposits dailyWithdrawals dailyNetLpFlow dailyActivationFees dailyActivationFeesToVault dailyProfitShares dailyCancelledProfit dailySubscriptionFees dailyProtocolFeesRouted dailyHypercoreFees dailyRescuedFunds dailyAccountReturnAmount dailyAccountPrincipalReturned dailyAccountGains dailyAccountLosses dailyPerformancePnl totalAccountsActivated totalAccountsActive totalAccountsClosed accountsActivatedToday accountsClosedToday navChange24h sharePriceChange24h return24hBps paused updatedAt`;
24
+ static VAULT_DAY_DATA_FIELDS = `id date dayNumber evmBalance totalAllocated totalAssets totalShares sharePrice dailyDeposits dailyWithdrawals dailyNetLpFlow dailyActivationFees dailyActivationFeesToVault dailyProfitShares dailyCancelledProfit dailySubscriptionFees dailyProtocolFeesRouted dailyHypercoreFees dailyRescuedFunds dailyAccountReturnAmount dailyAccountPrincipalReturned dailyAccountGains dailyAccountLosses dailyPerformancePnl dailyClosedAccountNetPnl cumulativeRealizedPnl totalAccountsActivated totalAccountsActive totalAccountsClosed accountsActivatedToday accountsClosedToday navChange24h sharePriceChange24h return24hBps realizedReturn24hBps paused updatedAt`;
25
25
  static LP_DAY_DATA_FIELDS = `id lp { id } date dayNumber shares sharesValue dailyDeposits dailyWithdrawals depositCount withdrawCount`;
26
+ // ── Challenge / B-book field sets (envio-unified schema) ──
27
+ static CHALLENGE_FIELDS = `id trader { id } builder { id address } payer vaultAddress allocation6 initialBalance6 phase failReason currentPhase reduceOnly totalPhases targetProfitBps finalTargetProfitBps drawdownBps dailyDrawdownEnabled tradingDaysEnabled profitableDaysRequired maxLeverageBps maxNotional6 maxOpenPositions minHoldBlocks freeBalance6 realizedPnl6 totalTradingFees6 equity6 highWaterMark6 dayStartEquity6 profitableDaysCount positionCount openPositionCount liquidationCount tradeCount totalVolume6 challengeFee6 builderAmount6 quoteHash quoteNonce quoteDeadline totalPayoutGross6 payoutCount promotedFundedAccount { id } activationFeePaid6 activatedAt challengeExpiry passedAt paperFundedAt failedAt closedAt promotedAt createdAt updatedAt`;
28
+ static CHALLENGE_BUILDER_FIELDS = `id address balance6 pendingPayouts6 delinquentSince isDelinquent activeChallengeExposure6 passedExposure6 paperFundedExposure6 queuedPayoutExposure6 pendingPassedAccounts pendingPayoutCount quoteEpoch totalFeesCollected6 totalDeposited6 totalWithdrawn6 totalInstantPaid6 totalQueuedPaid6 totalActivationFeesDebited6 challengesSold challengesPassed challengesPromoted registeredAt updatedAt`;
29
+ static CHALLENGE_POSITION_FIELDS = `id challenge { id } positionId market isLong status entryPrice marginOpen6 notionalOpen6 marginCurrent6 notionalCurrent6 cumulativeReducedNotional6 realizedPnl6 openFee6 closeFee6 exitPrice stopLossPrice takeProfitPrice exitOrderExecutedKind exitOrderTriggerPrice exitOrderRiskPrice exitOrderExecutedAt openedAtBlock openTx closeTx openedAt closedAt updatedAt`;
30
+ static CHALLENGE_TRADE_FIELDS = `id challenge { id } positionId kind market isLong margin6 notional6 price pnl6 fee6 freeBalanceAfter6 blockNumber timestamp txHash`;
31
+ static CHALLENGE_CHECKPOINT_FIELDS = `id challenge { id } kind equity6 highWaterMark6 dayStartEquity6 profitableDaysCount blockNumber timestamp txHash`;
32
+ static CHALLENGE_PAYOUT_FIELDS = `id challenge { id } trader { id } builderAddress requestedGross6 instantPaid6 queuedGross6 queuedPaid6 queueId fullyPaid requestedAt blockNumber txHash`;
33
+ static CHALLENGE_QUEUE_ENTRY_FIELDS = `id queueId challenge { id } builder { id } payoutId traderAddress originalGross6 remainingGross6 paidGross6 fullyPaid queuedAt lastPaidAt updatedAt`;
34
+ static CHALLENGE_DAY_DATA_FIELDS = `id date dayNumber challengesSold challengesPassed challengesPaperFunded challengesPromoted challengesFailed challengesClosed dailyChallengeFees6 dailyBuilderFees6 dailyPayoutGross6 dailyTradingVolume6 dailyTradingFees6 tradeCount updatedAt`;
35
+ static TRADER_FIELDS = `id challengesBought challengesPassed challengesPaperFunded challengesPromoted challengesFailed totalChallengeFeesPaid6 totalChallengePayoutGross6 firstSeenAt lastActionAt updatedAt`;
36
+ static JOURNEY_EVENT_FIELDS = `id trader { id } builderAddress kind challenge { id } fundedAccount { id } amount6 blockNumber timestamp txHash`;
37
+ static FOUNDER_PARTICIPANT_FIELDS = `id wallet firstSeenAt firstQualifiedAt firstQualifiedWeek founderRank founderTier founderBoostBps boostActive totalRawPoints totalFinalPoints totalPenaltyPoints challengePoints fundedPoints lpPoints spendPoints performancePoints lastActionAt updatedAt`;
38
+ static FOUNDER_WALLET_WEEK_FIELDS = `id wallet weekStart weekEnd rawSpendPoints rawPerformancePoints rawLpPoints rawPenaltyPoints finalSpendPoints finalPerformancePoints finalLpPoints finalPenaltyPoints totalFinalPoints liquidationCount breachCount founderTier founderBoostBps maturityBps updatedAt`;
39
+ static FOUNDER_POINT_EVENT_FIELDS = `id wallet weekStart source kind category rawPoints adjustedPoints finalPoints penaltyPoints maturityBps founderBoostBps qualityBps saturationBps walletMultiplierBps weeklyBoostBps amount accountSize relatedAccount builder txHash blockNumber timestamp`;
40
+ static FOUNDER_MULTIPLIER_FIELDS = `id wallet passExpiresAt activeFundedAccounts payoutBps payoutExpiresAt updatedAt`;
41
+ static FOUNDER_WEEKLY_BOOST_FIELDS = `id weekStart kind targetKind boostBps lpNeedBps utilizationBps updatedAt`;
26
42
  async getCachedProtocol() {
27
43
  if (this.cachedProtocol !== undefined)
28
44
  return this.cachedProtocol;
@@ -87,40 +103,40 @@ export class IndexerModule {
87
103
  async getVault(vaultAddress) {
88
104
  const resolved = await this.resolveVaultAddress(vaultAddress);
89
105
  if (!resolved) {
90
- const data = await this.query(`
91
- query { Vault(order_by: { updatedAt: desc }, limit: 1) { ${IndexerModule.VAULT_FIELDS} } }
106
+ const data = await this.query(`
107
+ query { Vault(order_by: { updatedAt: desc }, limit: 1) { ${IndexerModule.VAULT_FIELDS} } }
92
108
  `);
93
109
  return data.Vault[0] ?? null;
94
110
  }
95
- const data = await this.query(`
96
- query($id: String!) { Vault(where: { id: { _eq: $id } }) { ${IndexerModule.VAULT_FIELDS} } }
111
+ const data = await this.query(`
112
+ query($id: String!) { Vault(where: { id: { _eq: $id } }) { ${IndexerModule.VAULT_FIELDS} } }
97
113
  `, { id: resolved });
98
114
  return data.Vault[0] ?? null;
99
115
  }
100
116
  // ── LP ────────────────────────────────────────────
101
117
  async getLP(address) {
102
- const data = await this.query(`
103
- query($id: String!) { LiquidityProvider(where: { id: { _ilike: $id } }) { id shares totalDeposited totalWithdrawn depositCount withdrawCount lastActionAt } }
118
+ const data = await this.query(`
119
+ query($id: String!) { LiquidityProvider(where: { id: { _ilike: $id } }) { id shares totalDeposited totalWithdrawn depositCount withdrawCount lastActionAt } }
104
120
  `, { id: address });
105
121
  return data.LiquidityProvider[0] ?? null;
106
122
  }
107
123
  async getLPDeposits(address, p) {
108
- const data = await this.query(`
109
- query($lp: String!, $limit: Int, $offset: Int) {
110
- VaultDeposit(where: { lp_id: { _ilike: $lp } }, order_by: { timestamp: desc }, limit: $limit, offset: $offset) {
111
- id lp { id } amount sharesReceived timestamp txHash
112
- }
113
- }
124
+ const data = await this.query(`
125
+ query($lp: String!, $limit: Int, $offset: Int) {
126
+ VaultDeposit(where: { lp_id: { _ilike: $lp } }, order_by: { timestamp: desc }, limit: $limit, offset: $offset) {
127
+ id lp { id } amount sharesReceived timestamp txHash
128
+ }
129
+ }
114
130
  `, { lp: address, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
115
131
  return data.VaultDeposit;
116
132
  }
117
133
  async getLPWithdrawals(address, p) {
118
- const data = await this.query(`
119
- query($lp: String!, $limit: Int, $offset: Int) {
120
- VaultWithdrawal(where: { lp_id: { _ilike: $lp } }, order_by: { timestamp: desc }, limit: $limit, offset: $offset) {
121
- id lp { id } amount sharesBurned timestamp txHash
122
- }
123
- }
134
+ const data = await this.query(`
135
+ query($lp: String!, $limit: Int, $offset: Int) {
136
+ VaultWithdrawal(where: { lp_id: { _ilike: $lp } }, order_by: { timestamp: desc }, limit: $limit, offset: $offset) {
137
+ id lp { id } amount sharesBurned timestamp txHash
138
+ }
139
+ }
124
140
  `, { lp: address, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
125
141
  return data.VaultWithdrawal;
126
142
  }
@@ -128,80 +144,80 @@ export class IndexerModule {
128
144
  async getBuilder(address, vaultAddress) {
129
145
  const resolved = await this.resolveVaultAddress(vaultAddress);
130
146
  if (!resolved) {
131
- const data = await this.query(`
132
- query($address: String!) {
133
- Builder(where: { address: { _ilike: $address } }) { ${IndexerModule.BUILDER_FIELDS} }
134
- }
147
+ const data = await this.query(`
148
+ query($address: String!) {
149
+ Builder(where: { address: { _ilike: $address } }) { ${IndexerModule.BUILDER_FIELDS} }
150
+ }
135
151
  `, { address });
136
152
  return data.Builder[0] ?? null;
137
153
  }
138
- const data = await this.query(`
139
- query($address: String!, $vaultAddress: String) {
140
- Builder(where: { address: { _ilike: $address } vaultAddress: { _ilike: $vaultAddress } }) { ${IndexerModule.BUILDER_FIELDS} }
141
- }
154
+ const data = await this.query(`
155
+ query($address: String!, $vaultAddress: String) {
156
+ Builder(where: { address: { _ilike: $address } vaultAddress: { _ilike: $vaultAddress } }) { ${IndexerModule.BUILDER_FIELDS} }
157
+ }
142
158
  `, { address, vaultAddress: resolved });
143
159
  return data.Builder[0] ?? null;
144
160
  }
145
161
  async getDelegates(builder, vaultAddress) {
146
162
  const resolved = await this.resolveVaultAddress(vaultAddress);
147
163
  if (!resolved) {
148
- const data = await this.query(`
149
- query($builder: String!) {
150
- Delegate(where: { builderAddress: { _ilike: $builder } }) { ${IndexerModule.DELEGATE_FIELDS} }
151
- }
164
+ const data = await this.query(`
165
+ query($builder: String!) {
166
+ Delegate(where: { builderAddress: { _ilike: $builder } }) { ${IndexerModule.DELEGATE_FIELDS} }
167
+ }
152
168
  `, { builder });
153
169
  return data.Delegate;
154
170
  }
155
- const data = await this.query(`
156
- query($builder: String!, $vaultAddress: String) {
157
- Delegate(where: { builderAddress: { _ilike: $builder } vaultAddress: { _ilike: $vaultAddress } }) { ${IndexerModule.DELEGATE_FIELDS} }
158
- }
171
+ const data = await this.query(`
172
+ query($builder: String!, $vaultAddress: String) {
173
+ Delegate(where: { builderAddress: { _ilike: $builder } vaultAddress: { _ilike: $vaultAddress } }) { ${IndexerModule.DELEGATE_FIELDS} }
174
+ }
159
175
  `, { builder, vaultAddress: resolved });
160
176
  return data.Delegate;
161
177
  }
162
178
  // ── ACCOUNTS ──────────────────────────────────────
163
179
  async getAccount(address) {
164
- const data = await this.query(`
165
- query($id: String!) { FundedAccount(where: { id: { _ilike: $id } }) { ${IndexerModule.ACCOUNT_FIELDS} } }
180
+ const data = await this.query(`
181
+ query($id: String!) { FundedAccount(where: { id: { _ilike: $id } }) { ${IndexerModule.ACCOUNT_FIELDS} } }
166
182
  `, { id: address });
167
183
  return data.FundedAccount[0] ?? null;
168
184
  }
169
185
  async getAccountsByOwner(owner, p) {
170
- const data = await this.query(`
171
- query($owner: String!, $limit: Int, $offset: Int) {
172
- FundedAccount(where: { owner: { _ilike: $owner } }, order_by: { createdAt: desc }, limit: $limit, offset: $offset) { ${IndexerModule.ACCOUNT_FIELDS} }
173
- }
186
+ const data = await this.query(`
187
+ query($owner: String!, $limit: Int, $offset: Int) {
188
+ FundedAccount(where: { owner: { _ilike: $owner } }, order_by: { createdAt: desc }, limit: $limit, offset: $offset) { ${IndexerModule.ACCOUNT_FIELDS} }
189
+ }
174
190
  `, { owner: owner, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
175
191
  return data.FundedAccount;
176
192
  }
177
193
  async getAccountsByBuilder(builder, vaultAddress, p) {
178
194
  const resolved = await this.resolveVaultAddress(vaultAddress);
179
195
  if (!resolved) {
180
- const data = await this.query(`
181
- query($builder: String!, $limit: Int, $offset: Int) {
182
- FundedAccount(
183
- where: { builder: { address: { _ilike: $builder } } },
184
- order_by: { createdAt: desc }, limit: $limit, offset: $offset
185
- ) { ${IndexerModule.ACCOUNT_FIELDS} }
186
- }
196
+ const data = await this.query(`
197
+ query($builder: String!, $limit: Int, $offset: Int) {
198
+ FundedAccount(
199
+ where: { builder: { address: { _ilike: $builder } } },
200
+ order_by: { createdAt: desc }, limit: $limit, offset: $offset
201
+ ) { ${IndexerModule.ACCOUNT_FIELDS} }
202
+ }
187
203
  `, { builder, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
188
204
  return data.FundedAccount;
189
205
  }
190
- const data = await this.query(`
191
- query($builder: String!, $vaultAddress: String, $limit: Int, $offset: Int) {
192
- FundedAccount(
193
- where: { builder: { address: { _ilike: $builder } vaultAddress: { _ilike: $vaultAddress } } },
194
- order_by: { createdAt: desc }, limit: $limit, offset: $offset
195
- ) { ${IndexerModule.ACCOUNT_FIELDS} }
196
- }
206
+ const data = await this.query(`
207
+ query($builder: String!, $vaultAddress: String, $limit: Int, $offset: Int) {
208
+ FundedAccount(
209
+ where: { builder: { address: { _ilike: $builder } vaultAddress: { _ilike: $vaultAddress } } },
210
+ order_by: { createdAt: desc }, limit: $limit, offset: $offset
211
+ ) { ${IndexerModule.ACCOUNT_FIELDS} }
212
+ }
197
213
  `, { builder, vaultAddress: resolved, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
198
214
  return data.FundedAccount;
199
215
  }
200
216
  async getAccountsByState(state, p) {
201
- const data = await this.query(`
202
- query($state: accountstate!, $limit: Int, $offset: Int) {
203
- FundedAccount(where: { state: { _eq: $state } }, order_by: { updatedAt: desc }, limit: $limit, offset: $offset) { ${IndexerModule.ACCOUNT_FIELDS} }
204
- }
217
+ const data = await this.query(`
218
+ query($state: accountstate!, $limit: Int, $offset: Int) {
219
+ FundedAccount(where: { state: { _eq: $state } }, order_by: { updatedAt: desc }, limit: $limit, offset: $offset) { ${IndexerModule.ACCOUNT_FIELDS} }
220
+ }
205
221
  `, { state, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
206
222
  return data.FundedAccount;
207
223
  }
@@ -209,10 +225,10 @@ export class IndexerModule {
209
225
  const all = [];
210
226
  let offset = 0;
211
227
  while (true) {
212
- const data = await this.query(`
213
- query($states: [accountstate!]!, $limit: Int!, $offset: Int!) {
214
- FundedAccount(where: { state: { _in: $states } }, order_by: { updatedAt: desc }, limit: $limit, offset: $offset) { ${IndexerModule.ACCOUNT_FIELDS} }
215
- }
228
+ const data = await this.query(`
229
+ query($states: [accountstate!]!, $limit: Int!, $offset: Int!) {
230
+ FundedAccount(where: { state: { _in: $states } }, order_by: { updatedAt: desc }, limit: $limit, offset: $offset) { ${IndexerModule.ACCOUNT_FIELDS} }
231
+ }
216
232
  `, { states, limit: IndexerModule.PAGE_SIZE, offset });
217
233
  all.push(...data.FundedAccount);
218
234
  if (data.FundedAccount.length < IndexerModule.PAGE_SIZE)
@@ -225,10 +241,10 @@ export class IndexerModule {
225
241
  const all = [];
226
242
  let offset = 0;
227
243
  while (true) {
228
- const data = await this.query(`
229
- query($since: numeric!, $limit: Int!, $offset: Int!) {
230
- FundedAccount(where: { updatedAt: { _gt: $since } }, order_by: { updatedAt: asc }, limit: $limit, offset: $offset) { ${IndexerModule.ACCOUNT_FIELDS} }
231
- }
244
+ const data = await this.query(`
245
+ query($since: numeric!, $limit: Int!, $offset: Int!) {
246
+ FundedAccount(where: { updatedAt: { _gt: $since } }, order_by: { updatedAt: asc }, limit: $limit, offset: $offset) { ${IndexerModule.ACCOUNT_FIELDS} }
247
+ }
232
248
  `, { since, limit: IndexerModule.PAGE_SIZE, offset });
233
249
  all.push(...data.FundedAccount);
234
250
  if (data.FundedAccount.length < IndexerModule.PAGE_SIZE)
@@ -239,59 +255,59 @@ export class IndexerModule {
239
255
  }
240
256
  // ── HISTORY ───────────────────────────────────────
241
257
  async getCheckpoints(account, p) {
242
- const data = await this.query(`
243
- query($account: String!, $limit: Int, $offset: Int) {
244
- Checkpoint(where: { account_id: { _ilike: $account } }, order_by: { dayNumber: desc }, limit: $limit, offset: $offset) {
245
- id dayNumber accountValue previousValue profitable profitableDaysCount timestamp
246
- }
247
- }
258
+ const data = await this.query(`
259
+ query($account: String!, $limit: Int, $offset: Int) {
260
+ Checkpoint(where: { account_id: { _ilike: $account } }, order_by: { dayNumber: desc }, limit: $limit, offset: $offset) {
261
+ id dayNumber accountValue previousValue profitable profitableDaysCount timestamp
262
+ }
263
+ }
248
264
  `, { account: account, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
249
265
  return data.Checkpoint;
250
266
  }
251
267
  async getWithdrawals(account, p) {
252
- const data = await this.query(`
253
- query($account: String!, $limit: Int, $offset: Int) {
254
- ProfitWithdrawal(where: { account_id: { _ilike: $account } }, order_by: { requestedAt: desc }, limit: $limit, offset: $offset) {
255
- id profit ownerAmount vaultAmount protocolAmount status requestedAt claimedAt cancelledAt
256
- }
257
- }
268
+ const data = await this.query(`
269
+ query($account: String!, $limit: Int, $offset: Int) {
270
+ ProfitWithdrawal(where: { account_id: { _ilike: $account } }, order_by: { requestedAt: desc }, limit: $limit, offset: $offset) {
271
+ id profit ownerAmount vaultAmount protocolAmount status requestedAt claimedAt cancelledAt
272
+ }
273
+ }
258
274
  `, { account: account, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
259
275
  return data.ProfitWithdrawal;
260
276
  }
261
277
  async getSubscriptionPayments(account, p) {
262
- const data = await this.query(`
263
- query($account: String!, $limit: Int, $offset: Int) {
264
- SubscriptionPayment(where: { account_id: { _ilike: $account } }, order_by: { timestamp: desc }, limit: $limit, offset: $offset) {
265
- id amount paidUntil timestamp
266
- }
267
- }
278
+ const data = await this.query(`
279
+ query($account: String!, $limit: Int, $offset: Int) {
280
+ SubscriptionPayment(where: { account_id: { _ilike: $account } }, order_by: { timestamp: desc }, limit: $limit, offset: $offset) {
281
+ id amount paidUntil timestamp
282
+ }
283
+ }
268
284
  `, { account: account, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
269
285
  return data.SubscriptionPayment;
270
286
  }
271
287
  async getEvents(account, p) {
272
- const data = await this.query(`
273
- query($account: String!, $limit: Int, $offset: Int) {
274
- AccountEvent(where: { account_id: { _ilike: $account } }, order_by: { blockNumber: desc }, limit: $limit, offset: $offset) {
275
- id eventType data timestamp blockNumber txHash
276
- }
277
- }
288
+ const data = await this.query(`
289
+ query($account: String!, $limit: Int, $offset: Int) {
290
+ AccountEvent(where: { account_id: { _ilike: $account } }, order_by: { blockNumber: desc }, limit: $limit, offset: $offset) {
291
+ id eventType data timestamp blockNumber txHash
292
+ }
293
+ }
278
294
  `, { account: account, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
279
295
  return data.AccountEvent;
280
296
  }
281
297
  async getEventsByType(type, limit) {
282
- const data = await this.query(`
283
- query($type: String!, $limit: Int) {
284
- AccountEvent(where: { eventType: { _eq: $type } }, order_by: { blockNumber: desc }, limit: $limit) {
285
- id eventType data timestamp blockNumber txHash
286
- }
287
- }
298
+ const data = await this.query(`
299
+ query($type: String!, $limit: Int) {
300
+ AccountEvent(where: { eventType: { _eq: $type } }, order_by: { blockNumber: desc }, limit: $limit) {
301
+ id eventType data timestamp blockNumber txHash
302
+ }
303
+ }
288
304
  `, { type, limit: limit ?? 50 });
289
305
  return data.AccountEvent;
290
306
  }
291
307
  // ── PROTOCOL CONFIG ─────────────────────────────
292
308
  async getProtocolConfig() {
293
- const data = await this.query(`{
294
- ProtocolConfig { id vaultAddress factoryAddress updatedAt }
309
+ const data = await this.query(`{
310
+ ProtocolConfig { id vaultAddress factoryAddress updatedAt }
295
311
  }`);
296
312
  return data.ProtocolConfig[0] ?? null;
297
313
  }
@@ -299,26 +315,26 @@ export class IndexerModule {
299
315
  async getMainVaultConfig(vaultAddress) {
300
316
  const resolved = await this.resolveVaultAddress(vaultAddress);
301
317
  if (!resolved) {
302
- const data = await this.query(`
303
- query { MainVaultConfig(order_by: { updatedAt: desc }, limit: 1) { ${IndexerModule.MAIN_VAULT_CONFIG_FIELDS} } }
318
+ const data = await this.query(`
319
+ query { MainVaultConfig(order_by: { updatedAt: desc }, limit: 1) { ${IndexerModule.MAIN_VAULT_CONFIG_FIELDS} } }
304
320
  `);
305
321
  return data.MainVaultConfig[0] ?? null;
306
322
  }
307
- const data = await this.query(`
308
- query($id: String!) { MainVaultConfig(where: { id: { _eq: $id } }) { ${IndexerModule.MAIN_VAULT_CONFIG_FIELDS} } }
323
+ const data = await this.query(`
324
+ query($id: String!) { MainVaultConfig(where: { id: { _eq: $id } }) { ${IndexerModule.MAIN_VAULT_CONFIG_FIELDS} } }
309
325
  `, { id: resolved });
310
326
  return data.MainVaultConfig[0] ?? null;
311
327
  }
312
328
  async getFactoryConfig(factoryAddress) {
313
329
  const resolved = await this.resolveFactoryAddress(factoryAddress);
314
330
  if (!resolved) {
315
- const data = await this.query(`
316
- query { FactoryConfig(order_by: { updatedAt: desc }, limit: 1) { ${IndexerModule.FACTORY_CONFIG_FIELDS} } }
331
+ const data = await this.query(`
332
+ query { FactoryConfig(order_by: { updatedAt: desc }, limit: 1) { ${IndexerModule.FACTORY_CONFIG_FIELDS} } }
317
333
  `);
318
334
  return data.FactoryConfig[0] ?? null;
319
335
  }
320
- const data = await this.query(`
321
- query($id: String!) { FactoryConfig(where: { id: { _eq: $id } }) { ${IndexerModule.FACTORY_CONFIG_FIELDS} } }
336
+ const data = await this.query(`
337
+ query($id: String!) { FactoryConfig(where: { id: { _eq: $id } }) { ${IndexerModule.FACTORY_CONFIG_FIELDS} } }
322
338
  `, { id: resolved });
323
339
  return data.FactoryConfig[0] ?? null;
324
340
  }
@@ -347,51 +363,51 @@ export class IndexerModule {
347
363
  const whereBlock = whereClauses.length > 0
348
364
  ? `where: { ${whereClauses.join(" ")} }`
349
365
  : "";
350
- const data = await this.query(`
351
- query(${variableDefs.join(", ")}) {
352
- ConfigChange(
353
- ${whereBlock}
354
- order_by: [{ timestamp: desc }, { blockNumber: desc }]
355
- limit: $limit
356
- offset: $offset
357
- ) { ${IndexerModule.CONFIG_CHANGE_FIELDS} }
358
- }
366
+ const data = await this.query(`
367
+ query(${variableDefs.join(", ")}) {
368
+ ConfigChange(
369
+ ${whereBlock}
370
+ order_by: [{ timestamp: desc }, { blockNumber: desc }]
371
+ limit: $limit
372
+ offset: $offset
373
+ ) { ${IndexerModule.CONFIG_CHANGE_FIELDS} }
374
+ }
359
375
  `, variables);
360
376
  return data.ConfigChange;
361
377
  }
362
378
  async getVaultDayData(vaultAddress, p) {
363
379
  const resolved = await this.resolveVaultAddress(vaultAddress);
364
380
  if (!resolved) {
365
- const data = await this.query(`
366
- query($limit: Int, $offset: Int) {
367
- VaultDayData(order_by: [{ date: desc }, { updatedAt: desc }], limit: $limit, offset: $offset) {
368
- ${IndexerModule.VAULT_DAY_DATA_FIELDS}
369
- }
370
- }
381
+ const data = await this.query(`
382
+ query($limit: Int, $offset: Int) {
383
+ VaultDayData(order_by: [{ date: desc }, { updatedAt: desc }], limit: $limit, offset: $offset) {
384
+ ${IndexerModule.VAULT_DAY_DATA_FIELDS}
385
+ }
386
+ }
371
387
  `, { limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
372
388
  return data.VaultDayData;
373
389
  }
374
- const data = await this.query(`
375
- query($vaultAddress: String!, $limit: Int, $offset: Int) {
376
- VaultDayData(
377
- where: { id: { _ilike: $vaultAddress } }
378
- order_by: [{ date: desc }, { updatedAt: desc }]
379
- limit: $limit, offset: $offset
380
- ) { ${IndexerModule.VAULT_DAY_DATA_FIELDS} }
381
- }
390
+ const data = await this.query(`
391
+ query($vaultAddress: String!, $limit: Int, $offset: Int) {
392
+ VaultDayData(
393
+ where: { id: { _ilike: $vaultAddress } }
394
+ order_by: [{ date: desc }, { updatedAt: desc }]
395
+ limit: $limit, offset: $offset
396
+ ) { ${IndexerModule.VAULT_DAY_DATA_FIELDS} }
397
+ }
382
398
  `, { vaultAddress: `${resolved}-%`, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
383
399
  return data.VaultDayData;
384
400
  }
385
401
  async getLPDayData(address, p) {
386
- const data = await this.query(`
387
- query($lp: String!, $limit: Int, $offset: Int) {
388
- LiquidityProviderDayData(
389
- where: { lp_id: { _ilike: $lp } }
390
- order_by: [{ date: desc }, { dayNumber: desc }]
391
- limit: $limit
392
- offset: $offset
393
- ) { ${IndexerModule.LP_DAY_DATA_FIELDS} }
394
- }
402
+ const data = await this.query(`
403
+ query($lp: String!, $limit: Int, $offset: Int) {
404
+ LiquidityProviderDayData(
405
+ where: { lp_id: { _ilike: $lp } }
406
+ order_by: [{ date: desc }, { dayNumber: desc }]
407
+ limit: $limit
408
+ offset: $offset
409
+ ) { ${IndexerModule.LP_DAY_DATA_FIELDS} }
410
+ }
395
411
  `, {
396
412
  lp: address,
397
413
  limit: p?.limit ?? 50,
@@ -402,18 +418,198 @@ export class IndexerModule {
402
418
  async getAllowedPerps(vaultAddress) {
403
419
  const resolved = await this.resolveVaultAddress(vaultAddress);
404
420
  if (!resolved) {
405
- const data = await this.query(`
406
- query { AllowedPerp(where: { allowed: { _eq: true } }) { id vaultAddress perpIndex allowed } }
421
+ const data = await this.query(`
422
+ query { AllowedPerp(where: { allowed: { _eq: true } }) { id vaultAddress perpIndex allowed } }
407
423
  `);
408
424
  return data.AllowedPerp;
409
425
  }
410
- const data = await this.query(`
411
- query($vaultAddress: String) {
412
- AllowedPerp(where: { allowed: { _eq: true } vaultAddress: { _ilike: $vaultAddress } }) { id vaultAddress perpIndex allowed }
413
- }
426
+ const data = await this.query(`
427
+ query($vaultAddress: String) {
428
+ AllowedPerp(where: { allowed: { _eq: true } vaultAddress: { _ilike: $vaultAddress } }) { id vaultAddress perpIndex allowed }
429
+ }
414
430
  `, { vaultAddress: resolved });
415
431
  return data.AllowedPerp;
416
432
  }
433
+ // ── CHALLENGE / B-BOOK (envio-unified) ────────────
434
+ async getChallenge(address) {
435
+ const data = await this.query(`
436
+ query($id: String!) { Challenge(where: { id: { _ilike: $id } }) { ${IndexerModule.CHALLENGE_FIELDS} } }
437
+ `, { id: address });
438
+ return data.Challenge[0] ?? null;
439
+ }
440
+ async getChallengesByTrader(trader, p) {
441
+ const data = await this.query(`
442
+ query($trader: String!, $limit: Int, $offset: Int) {
443
+ Challenge(where: { trader_id: { _ilike: $trader } }, order_by: { createdAt: desc }, limit: $limit, offset: $offset) { ${IndexerModule.CHALLENGE_FIELDS} }
444
+ }
445
+ `, { trader, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
446
+ return data.Challenge;
447
+ }
448
+ async getChallengesByBuilder(builder, p) {
449
+ const data = await this.query(`
450
+ query($builder: String!, $limit: Int, $offset: Int) {
451
+ Challenge(where: { builder_id: { _ilike: $builder } }, order_by: { createdAt: desc }, limit: $limit, offset: $offset) { ${IndexerModule.CHALLENGE_FIELDS} }
452
+ }
453
+ `, { builder, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
454
+ return data.Challenge;
455
+ }
456
+ async getChallengesByPhase(phase, p) {
457
+ const data = await this.query(`
458
+ query($phase: challengephase!, $limit: Int, $offset: Int) {
459
+ Challenge(where: { phase: { _eq: $phase } }, order_by: { updatedAt: desc }, limit: $limit, offset: $offset) { ${IndexerModule.CHALLENGE_FIELDS} }
460
+ }
461
+ `, { phase, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
462
+ return data.Challenge;
463
+ }
464
+ async getChallengeBuilder(address) {
465
+ const data = await this.query(`
466
+ query($id: String!) { ChallengeBuilder(where: { id: { _ilike: $id } }) { ${IndexerModule.CHALLENGE_BUILDER_FIELDS} } }
467
+ `, { id: address });
468
+ return data.ChallengeBuilder[0] ?? null;
469
+ }
470
+ async getChallengePositions(challenge, p) {
471
+ const openFilter = p?.openOnly ? `status: { _eq: Open }` : "";
472
+ const data = await this.query(`
473
+ query($challenge: String!, $limit: Int, $offset: Int) {
474
+ ChallengePosition(where: { challenge_id: { _ilike: $challenge } ${openFilter} }, order_by: { openedAt: desc }, limit: $limit, offset: $offset) { ${IndexerModule.CHALLENGE_POSITION_FIELDS} }
475
+ }
476
+ `, { challenge, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
477
+ return data.ChallengePosition;
478
+ }
479
+ async getChallengeTrades(challenge, p) {
480
+ const data = await this.query(`
481
+ query($challenge: String!, $limit: Int, $offset: Int) {
482
+ ChallengeTrade(where: { challenge_id: { _ilike: $challenge } }, order_by: { timestamp: desc }, limit: $limit, offset: $offset) { ${IndexerModule.CHALLENGE_TRADE_FIELDS} }
483
+ }
484
+ `, { challenge, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
485
+ return data.ChallengeTrade;
486
+ }
487
+ async getChallengeCheckpoints(challenge, p) {
488
+ const data = await this.query(`
489
+ query($challenge: String!, $limit: Int, $offset: Int) {
490
+ ChallengeCheckpoint(where: { challenge_id: { _ilike: $challenge } }, order_by: { timestamp: desc }, limit: $limit, offset: $offset) { ${IndexerModule.CHALLENGE_CHECKPOINT_FIELDS} }
491
+ }
492
+ `, { challenge, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
493
+ return data.ChallengeCheckpoint;
494
+ }
495
+ async getChallengePayouts(filter, p) {
496
+ const clauses = [];
497
+ const variableDefs = ["$limit: Int", "$offset: Int"];
498
+ const variables = { limit: p?.limit ?? 50, offset: p?.offset ?? 0 };
499
+ if (filter.challenge) {
500
+ variableDefs.push("$challenge: String!");
501
+ clauses.push("challenge_id: { _ilike: $challenge }");
502
+ variables.challenge = filter.challenge;
503
+ }
504
+ if (filter.trader) {
505
+ variableDefs.push("$trader: String!");
506
+ clauses.push("trader_id: { _ilike: $trader }");
507
+ variables.trader = filter.trader;
508
+ }
509
+ if (filter.builder) {
510
+ variableDefs.push("$builder: String!");
511
+ clauses.push("builderAddress: { _ilike: $builder }");
512
+ variables.builder = filter.builder;
513
+ }
514
+ const whereBlock = clauses.length > 0 ? `where: { ${clauses.join(" ")} }` : "";
515
+ const data = await this.query(`
516
+ query(${variableDefs.join(", ")}) {
517
+ ChallengePayout(${whereBlock} order_by: { requestedAt: desc }, limit: $limit, offset: $offset) { ${IndexerModule.CHALLENGE_PAYOUT_FIELDS} }
518
+ }
519
+ `, variables);
520
+ return data.ChallengePayout;
521
+ }
522
+ /** Live FIFO payout queue of a builder (unpaid entries, oldest first). */
523
+ async getPayoutQueue(builder, p) {
524
+ const data = await this.query(`
525
+ query($builder: String!, $limit: Int, $offset: Int) {
526
+ ChallengePayoutQueueEntry(where: { builder_id: { _ilike: $builder } fullyPaid: { _eq: false } }, order_by: { queueId: asc }, limit: $limit, offset: $offset) { ${IndexerModule.CHALLENGE_QUEUE_ENTRY_FIELDS} }
527
+ }
528
+ `, { builder, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
529
+ return data.ChallengePayoutQueueEntry;
530
+ }
531
+ async getChallengeDayData(p) {
532
+ const data = await this.query(`
533
+ query($limit: Int, $offset: Int) {
534
+ ChallengeDayData(order_by: { date: desc }, limit: $limit, offset: $offset) { ${IndexerModule.CHALLENGE_DAY_DATA_FIELDS} }
535
+ }
536
+ `, { limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
537
+ return data.ChallengeDayData;
538
+ }
539
+ // ── BRIDGE / JOURNEY ──────────────────────────────
540
+ async getTrader(address) {
541
+ const data = await this.query(`
542
+ query($id: String!) { Trader(where: { id: { _ilike: $id } }) { ${IndexerModule.TRADER_FIELDS} } }
543
+ `, { id: address });
544
+ return data.Trader[0] ?? null;
545
+ }
546
+ /** Cross-system timeline (challenge ↔ funded) of a trader, newest first. */
547
+ async getTraderJourney(trader, p) {
548
+ const data = await this.query(`
549
+ query($trader: String!, $limit: Int, $offset: Int) {
550
+ JourneyEvent(where: { trader_id: { _ilike: $trader } }, order_by: { timestamp: desc }, limit: $limit, offset: $offset) { ${IndexerModule.JOURNEY_EVENT_FIELDS} }
551
+ }
552
+ `, { trader, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
553
+ return data.JourneyEvent;
554
+ }
555
+ // ── FOUNDER POINTS ────────────────────────────────
556
+ async getFounderParticipant(wallet) {
557
+ const data = await this.query(`
558
+ query($id: String!) { FounderParticipant(where: { id: { _ilike: $id } }) { ${IndexerModule.FOUNDER_PARTICIPANT_FIELDS} } }
559
+ `, { id: wallet });
560
+ return data.FounderParticipant[0] ?? null;
561
+ }
562
+ /** Lifetime leaderboard by total final points. */
563
+ async getFounderLeaderboard(p) {
564
+ const data = await this.query(`
565
+ query($limit: Int, $offset: Int) {
566
+ FounderParticipant(order_by: { totalFinalPoints: desc }, limit: $limit, offset: $offset) { ${IndexerModule.FOUNDER_PARTICIPANT_FIELDS} }
567
+ }
568
+ `, { limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
569
+ return data.FounderParticipant;
570
+ }
571
+ /** Weekly leaderboard for one epoch week (weekStart = unix seconds of the week boundary). */
572
+ async getFounderWeeklyLeaderboard(weekStart, p) {
573
+ const data = await this.query(`
574
+ query($weekStart: numeric!, $limit: Int, $offset: Int) {
575
+ FounderWalletWeek(where: { weekStart: { _eq: $weekStart } }, order_by: { totalFinalPoints: desc }, limit: $limit, offset: $offset) { ${IndexerModule.FOUNDER_WALLET_WEEK_FIELDS} }
576
+ }
577
+ `, { weekStart, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
578
+ return data.FounderWalletWeek;
579
+ }
580
+ async getFounderWalletWeeks(wallet, p) {
581
+ const data = await this.query(`
582
+ query($wallet: String!, $limit: Int, $offset: Int) {
583
+ FounderWalletWeek(where: { wallet: { _ilike: $wallet } }, order_by: { weekStart: desc }, limit: $limit, offset: $offset) { ${IndexerModule.FOUNDER_WALLET_WEEK_FIELDS} }
584
+ }
585
+ `, { wallet, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
586
+ return data.FounderWalletWeek;
587
+ }
588
+ /** Canonical append-only point journal of a wallet, newest first. */
589
+ async getFounderPointEvents(wallet, p) {
590
+ const data = await this.query(`
591
+ query($wallet: String!, $limit: Int, $offset: Int) {
592
+ FounderPointEvent(where: { wallet: { _ilike: $wallet } }, order_by: { timestamp: desc }, limit: $limit, offset: $offset) { ${IndexerModule.FOUNDER_POINT_EVENT_FIELDS} }
593
+ }
594
+ `, { wallet, limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
595
+ return data.FounderPointEvent;
596
+ }
597
+ /** Active skill multipliers (pass/activation/realization) of a wallet. */
598
+ async getFounderMultiplier(wallet) {
599
+ const data = await this.query(`
600
+ query($id: String!) { FounderMultiplier(where: { id: { _ilike: $id } }) { ${IndexerModule.FOUNDER_MULTIPLIER_FIELDS} } }
601
+ `, { id: wallet });
602
+ return data.FounderMultiplier[0] ?? null;
603
+ }
604
+ /** Weekly rotating boost entries (deterministic calendar), newest first. */
605
+ async getFounderWeeklyBoosts(p) {
606
+ const data = await this.query(`
607
+ query($limit: Int, $offset: Int) {
608
+ FounderWeeklyBoost(order_by: { weekStart: desc }, limit: $limit, offset: $offset) { ${IndexerModule.FOUNDER_WEEKLY_BOOST_FIELDS} }
609
+ }
610
+ `, { limit: p?.limit ?? 50, offset: p?.offset ?? 0 });
611
+ return data.FounderWeeklyBoost;
612
+ }
417
613
  // ── SUBSCRIPTIONS (Hasura graphql-transport-ws) ───
418
614
  ensureWs() {
419
615
  const WebSocketCtor = (this.transports.webSocketCtor ?? globalThis.WebSocket);
@@ -493,6 +689,14 @@ export class IndexerModule {
493
689
  subscribeAllowedPerps(cb) {
494
690
  return this.subscribe(`subscription { AllowedPerp(where: { allowed: { _eq: true } }) { id vaultAddress perpIndex allowed } }`, undefined, (data) => cb(data.AllowedPerp));
495
691
  }
692
+ subscribeChallenge(address, cb) {
693
+ return this.subscribe(`subscription($id: String!) { Challenge(where: { id: { _ilike: $id } }) { ${IndexerModule.CHALLENGE_FIELDS} } }`, { id: address }, (data) => { if (data.Challenge[0])
694
+ cb(data.Challenge[0]); });
695
+ }
696
+ /** Live view of a builder's unpaid FIFO payout queue. */
697
+ subscribePayoutQueue(builder, cb) {
698
+ return this.subscribe(`subscription($builder: String!) { ChallengePayoutQueueEntry(where: { builder_id: { _ilike: $builder } fullyPaid: { _eq: false } }, order_by: { queueId: asc }) { ${IndexerModule.CHALLENGE_QUEUE_ENTRY_FIELDS} } }`, { builder }, (data) => cb(data.ChallengePayoutQueueEntry));
699
+ }
496
700
  disconnect() {
497
701
  if (this.reconnectTimer) {
498
702
  clearTimeout(this.reconnectTimer);