tapimo 0.7.2 → 0.8.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 (294) hide show
  1. package/README.md +10 -7
  2. package/dist/ApiKey.d.ts +3 -0
  3. package/dist/ApiKey.d.ts.map +1 -1
  4. package/dist/ApiKey.js +10 -0
  5. package/dist/ApiKey.js.map +1 -1
  6. package/dist/ApiKeys.d.ts +7 -3
  7. package/dist/ApiKeys.d.ts.map +1 -1
  8. package/dist/ApiKeys.js +9 -2
  9. package/dist/ApiKeys.js.map +1 -1
  10. package/dist/App.d.ts +20434 -19484
  11. package/dist/App.d.ts.map +1 -1
  12. package/dist/App.js +62 -4
  13. package/dist/App.js.map +1 -1
  14. package/dist/admin/App.d.ts +84 -74
  15. package/dist/admin/App.d.ts.map +1 -1
  16. package/dist/admin/apps/api-keys.d.ts +14 -1
  17. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  18. package/dist/admin/apps/api-keys.js +6 -2
  19. package/dist/admin/apps/api-keys.js.map +1 -1
  20. package/dist/admin/apps/organizations.d.ts +2 -0
  21. package/dist/admin/apps/organizations.d.ts.map +1 -1
  22. package/dist/admin/apps/verified-tokens.d.ts +168 -168
  23. package/dist/admin/ui.generated.d.ts +1 -1
  24. package/dist/admin/ui.generated.js +67 -67
  25. package/dist/admin/ui.generated.js.map +1 -1
  26. package/dist/analytics/Analytics.d.ts +2 -0
  27. package/dist/analytics/Analytics.d.ts.map +1 -1
  28. package/dist/analytics/Analytics.js +3 -0
  29. package/dist/analytics/Analytics.js.map +1 -1
  30. package/dist/apps/data/App.d.ts +10305 -12785
  31. package/dist/apps/data/App.d.ts.map +1 -1
  32. package/dist/apps/data/App.js +4 -8
  33. package/dist/apps/data/App.js.map +1 -1
  34. package/dist/apps/data/routes/activities.d.ts +24 -24
  35. package/dist/apps/data/routes/addresses.d.ts +288 -288
  36. package/dist/apps/data/routes/balances.d.ts +6 -6
  37. package/dist/apps/data/routes/blocks.d.ts +39 -39
  38. package/dist/apps/data/routes/coingecko.d.ts +170 -170
  39. package/dist/apps/data/routes/earn.d.ts +436 -6
  40. package/dist/apps/data/routes/earn.d.ts.map +1 -1
  41. package/dist/apps/data/routes/earn.js +631 -4
  42. package/dist/apps/data/routes/earn.js.map +1 -1
  43. package/dist/apps/data/routes/exchanges.d.ts +10 -10
  44. package/dist/apps/data/routes/fee-amm.d.ts +2 -2
  45. package/dist/apps/data/routes/indexer.d.ts +6 -6
  46. package/dist/apps/data/routes/indexer.js +4 -1
  47. package/dist/apps/data/routes/indexer.js.map +1 -1
  48. package/dist/apps/data/routes/receipts.d.ts +235 -235
  49. package/dist/apps/data/routes/rpc.d.ts +1 -1
  50. package/dist/apps/data/routes/rpc.js +4 -1
  51. package/dist/apps/data/routes/rpc.js.map +1 -1
  52. package/dist/apps/data/routes/tokenlist.d.ts +36 -36
  53. package/dist/apps/data/routes/tokens.d.ts +6 -6
  54. package/dist/apps/data/routes/transactions.d.ts +2 -2
  55. package/dist/apps/data/routes/transfers.d.ts +1 -1
  56. package/dist/apps/data/routes/valuation.d.ts +1 -1
  57. package/dist/apps/data/routes/verified-tokens.d.ts +36 -36
  58. package/dist/apps/data/routes/webhooks.d.ts +9 -9
  59. package/dist/apps/data/routes/zones.d.ts +14 -14
  60. package/dist/apps/funding/Access.d.ts +16 -0
  61. package/dist/apps/funding/Access.d.ts.map +1 -0
  62. package/dist/apps/funding/Access.js +22 -0
  63. package/dist/apps/funding/Access.js.map +1 -0
  64. package/dist/apps/{data/routes/funding.d.ts → funding/App.d.ts} +1717 -3035
  65. package/dist/apps/funding/App.d.ts.map +1 -0
  66. package/dist/apps/funding/App.js +46 -0
  67. package/dist/apps/funding/App.js.map +1 -0
  68. package/dist/apps/funding/Inventory.d.ts +5 -0
  69. package/dist/apps/funding/Inventory.d.ts.map +1 -0
  70. package/dist/apps/funding/Inventory.js +25 -0
  71. package/dist/apps/funding/Inventory.js.map +1 -0
  72. package/dist/apps/funding/ProviderAttempts.d.ts +5 -0
  73. package/dist/apps/funding/ProviderAttempts.d.ts.map +1 -0
  74. package/dist/apps/funding/ProviderAttempts.js +24 -0
  75. package/dist/apps/funding/ProviderAttempts.js.map +1 -0
  76. package/dist/apps/funding/index.d.ts +2 -0
  77. package/dist/apps/funding/index.d.ts.map +1 -0
  78. package/dist/apps/funding/index.js +2 -0
  79. package/dist/apps/funding/index.js.map +1 -0
  80. package/dist/apps/funding/routes/chains.d.ts +169 -0
  81. package/dist/apps/funding/routes/chains.d.ts.map +1 -0
  82. package/dist/apps/funding/routes/chains.js +80 -0
  83. package/dist/apps/funding/routes/chains.js.map +1 -0
  84. package/dist/apps/funding/routes/deposit-addresses.d.ts +2388 -0
  85. package/dist/apps/funding/routes/deposit-addresses.d.ts.map +1 -0
  86. package/dist/apps/funding/routes/deposit-addresses.js +860 -0
  87. package/dist/apps/funding/routes/deposit-addresses.js.map +1 -0
  88. package/dist/apps/funding/routes/providers.d.ts +91 -0
  89. package/dist/apps/funding/routes/providers.d.ts.map +1 -0
  90. package/dist/apps/funding/routes/providers.js +56 -0
  91. package/dist/apps/funding/routes/providers.js.map +1 -0
  92. package/dist/apps/funding/routes/quotes.d.ts +426 -0
  93. package/dist/apps/funding/routes/quotes.d.ts.map +1 -0
  94. package/dist/apps/funding/routes/quotes.js +188 -0
  95. package/dist/apps/funding/routes/quotes.js.map +1 -0
  96. package/dist/apps/funding/routes/transfers.d.ts +1999 -0
  97. package/dist/apps/funding/routes/transfers.d.ts.map +1 -0
  98. package/dist/apps/funding/routes/transfers.js +614 -0
  99. package/dist/apps/funding/routes/transfers.js.map +1 -0
  100. package/dist/apps/index.d.ts +1 -0
  101. package/dist/apps/index.d.ts.map +1 -1
  102. package/dist/apps/index.js +1 -0
  103. package/dist/apps/index.js.map +1 -1
  104. package/dist/apps/management/App.d.ts +430 -165
  105. package/dist/apps/management/App.d.ts.map +1 -1
  106. package/dist/apps/management/routes/api-keys.d.ts +298 -21
  107. package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
  108. package/dist/apps/management/routes/api-keys.js +75 -1
  109. package/dist/apps/management/routes/api-keys.js.map +1 -1
  110. package/dist/apps/management/routes/billing.d.ts +6 -6
  111. package/dist/apps/management/routes/faucet.d.ts +35 -35
  112. package/dist/apps/management/routes/invitations.d.ts +48 -48
  113. package/dist/apps/management/routes/invite-links.d.ts +38 -38
  114. package/dist/apps/management/routes/members.d.ts +69 -69
  115. package/dist/apps/management/routes/orgs.d.ts +37 -37
  116. package/dist/apps/management/routes/projects.d.ts +25 -25
  117. package/dist/apps/management/routes/scopes.d.ts +1 -1
  118. package/dist/apps/management/routes/usage.d.ts +72 -72
  119. package/dist/apps/management/routes/verified-token-requests.d.ts +18 -18
  120. package/dist/apps/management/routes/webhooks.d.ts +128 -128
  121. package/dist/apps/mcp.d.ts +2 -3
  122. package/dist/apps/mcp.d.ts.map +1 -1
  123. package/dist/apps/mcp.js +16 -14
  124. package/dist/apps/mcp.js.map +1 -1
  125. package/dist/apps/metadata.d.ts +4 -0
  126. package/dist/apps/metadata.d.ts.map +1 -1
  127. package/dist/apps/metadata.js +10 -0
  128. package/dist/apps/metadata.js.map +1 -1
  129. package/dist/apps/mpp/App.d.ts +2 -2
  130. package/dist/cloudflare.d.ts +50 -0
  131. package/dist/cloudflare.d.ts.map +1 -1
  132. package/dist/cloudflare.js +178 -0
  133. package/dist/cloudflare.js.map +1 -1
  134. package/dist/db/Db.d.ts +2 -0
  135. package/dist/db/Db.d.ts.map +1 -1
  136. package/dist/db/Db.js +37 -0
  137. package/dist/db/Db.js.map +1 -1
  138. package/dist/db/Schema.d.ts +12 -0
  139. package/dist/db/Schema.d.ts.map +1 -1
  140. package/dist/db/Schema.js +20 -0
  141. package/dist/db/Schema.js.map +1 -1
  142. package/dist/db/tables/fundingDepositAddresses.d.ts +13 -0
  143. package/dist/db/tables/fundingDepositAddresses.d.ts.map +1 -1
  144. package/dist/db/tables/fundingDepositAddresses.js +12 -0
  145. package/dist/db/tables/fundingDepositAddresses.js.map +1 -1
  146. package/dist/db/tables/fundingDepositRequestObservations.d.ts +45 -0
  147. package/dist/db/tables/fundingDepositRequestObservations.d.ts.map +1 -0
  148. package/dist/db/tables/fundingDepositRequestObservations.js +46 -0
  149. package/dist/db/tables/fundingDepositRequestObservations.js.map +1 -0
  150. package/dist/db/tables/fundingDeposits.d.ts +57 -1
  151. package/dist/db/tables/fundingDeposits.d.ts.map +1 -1
  152. package/dist/db/tables/fundingDeposits.js +82 -0
  153. package/dist/db/tables/fundingDeposits.js.map +1 -1
  154. package/dist/internal/Auth.d.ts +11 -11
  155. package/dist/internal/Auth.d.ts.map +1 -1
  156. package/dist/internal/Auth.js +41 -15
  157. package/dist/internal/Auth.js.map +1 -1
  158. package/dist/internal/Cache.js +1 -1
  159. package/dist/internal/Cache.js.map +1 -1
  160. package/dist/internal/EdgeCache.d.ts +2 -2
  161. package/dist/internal/EdgeCache.d.ts.map +1 -1
  162. package/dist/internal/EdgeCache.js +10 -4
  163. package/dist/internal/EdgeCache.js.map +1 -1
  164. package/dist/internal/IpAllowlist.d.ts +15 -0
  165. package/dist/internal/IpAllowlist.d.ts.map +1 -0
  166. package/dist/internal/IpAllowlist.js +27 -0
  167. package/dist/internal/IpAllowlist.js.map +1 -0
  168. package/dist/internal/OpenApi.d.ts +1 -1
  169. package/dist/internal/OpenApi.js +1 -1
  170. package/dist/internal/OpenApi.js.map +1 -1
  171. package/dist/internal/Tidx.d.ts +6 -0
  172. package/dist/internal/Tidx.d.ts.map +1 -1
  173. package/dist/internal/Tidx.js +13 -3
  174. package/dist/internal/Tidx.js.map +1 -1
  175. package/dist/internal/Viem.d.ts +8 -0
  176. package/dist/internal/Viem.d.ts.map +1 -1
  177. package/dist/internal/Viem.js +12 -5
  178. package/dist/internal/Viem.js.map +1 -1
  179. package/dist/internal/funding/Deposit.d.ts +42 -0
  180. package/dist/internal/funding/Deposit.d.ts.map +1 -1
  181. package/dist/internal/funding/Deposit.js +37 -5
  182. package/dist/internal/funding/Deposit.js.map +1 -1
  183. package/dist/internal/funding/Evidence.d.ts +1 -5
  184. package/dist/internal/funding/Evidence.d.ts.map +1 -1
  185. package/dist/internal/funding/Evidence.js +4 -3
  186. package/dist/internal/funding/Evidence.js.map +1 -1
  187. package/dist/internal/funding/Provider.d.ts +102 -0
  188. package/dist/internal/funding/Provider.d.ts.map +1 -1
  189. package/dist/internal/funding/Provider.js +5 -0
  190. package/dist/internal/funding/Provider.js.map +1 -1
  191. package/dist/internal/funding/Reconciliation.d.ts +16 -2
  192. package/dist/internal/funding/Reconciliation.d.ts.map +1 -1
  193. package/dist/internal/funding/Reconciliation.js +257 -48
  194. package/dist/internal/funding/Reconciliation.js.map +1 -1
  195. package/dist/internal/funding/SourceObservation.d.ts +108 -0
  196. package/dist/internal/funding/SourceObservation.d.ts.map +1 -0
  197. package/dist/internal/funding/SourceObservation.js +143 -0
  198. package/dist/internal/funding/SourceObservation.js.map +1 -0
  199. package/dist/internal/funding/Subsidy.d.ts +2 -2
  200. package/dist/internal/funding/Subsidy.d.ts.map +1 -1
  201. package/dist/internal/funding/Subsidy.js +1 -1
  202. package/dist/internal/funding/Subsidy.js.map +1 -1
  203. package/dist/internal/funding/index.d.ts +1 -0
  204. package/dist/internal/funding/index.d.ts.map +1 -1
  205. package/dist/internal/funding/index.js +1 -0
  206. package/dist/internal/funding/index.js.map +1 -1
  207. package/dist/internal/funding/providers/relay.d.ts +43 -1
  208. package/dist/internal/funding/providers/relay.d.ts.map +1 -1
  209. package/dist/internal/funding/providers/relay.js +434 -27
  210. package/dist/internal/funding/providers/relay.js.map +1 -1
  211. package/package.json +3 -3
  212. package/src/ApiKey.test.ts +35 -0
  213. package/src/ApiKey.ts +27 -0
  214. package/src/ApiKeys.test.ts +29 -0
  215. package/src/ApiKeys.ts +11 -3
  216. package/src/App.test.ts +23 -5
  217. package/src/App.ts +76 -5
  218. package/src/Client.test-d.ts +171 -19
  219. package/src/admin/apps/api-keys.test.ts +25 -1
  220. package/src/admin/apps/api-keys.ts +6 -2
  221. package/src/admin/ui.generated.ts +67 -67
  222. package/src/analytics/Analytics.ts +4 -0
  223. package/src/apps/composition.test.ts +100 -2
  224. package/src/apps/data/App.test.ts +0 -12
  225. package/src/apps/data/App.ts +4 -8
  226. package/src/apps/data/routes/earn.test.ts +283 -0
  227. package/src/apps/data/routes/earn.ts +800 -3
  228. package/src/apps/data/routes/indexer.ts +2 -1
  229. package/src/apps/data/routes/rpc.ts +2 -0
  230. package/src/apps/data/routes/tokens.test.ts +6 -8
  231. package/src/apps/funding/Access.ts +26 -0
  232. package/src/apps/funding/App.test.ts +78 -0
  233. package/src/apps/funding/App.ts +63 -0
  234. package/src/apps/funding/Inventory.ts +30 -0
  235. package/src/apps/funding/ProviderAttempts.ts +26 -0
  236. package/src/apps/funding/index.ts +1 -0
  237. package/src/apps/funding/routes/chains.test.ts +78 -0
  238. package/src/apps/funding/routes/chains.ts +101 -0
  239. package/src/apps/funding/routes/deposit-addresses.test.ts +1628 -0
  240. package/src/apps/funding/routes/deposit-addresses.ts +1015 -0
  241. package/src/apps/funding/routes/providers.test.ts +165 -0
  242. package/src/apps/funding/routes/providers.ts +73 -0
  243. package/src/apps/funding/routes/quotes.test.ts +511 -0
  244. package/src/apps/funding/routes/quotes.ts +205 -0
  245. package/src/apps/funding/routes/transfers.test.ts +1255 -0
  246. package/src/apps/funding/routes/transfers.ts +704 -0
  247. package/src/apps/index.ts +1 -0
  248. package/src/apps/management/routes/api-keys.test.ts +98 -0
  249. package/src/apps/management/routes/api-keys.ts +96 -1
  250. package/src/apps/mcp.test.ts +17 -2
  251. package/src/apps/mcp.ts +18 -13
  252. package/src/apps/metadata.ts +12 -0
  253. package/src/apps/mpp/internal/Policy.test.ts +7 -1
  254. package/src/cloudflare.ts +279 -0
  255. package/src/db/Db.ts +62 -0
  256. package/src/db/Schema.ts +24 -0
  257. package/src/db/tables/fundingDepositAddresses.ts +28 -0
  258. package/src/db/tables/fundingDepositRequestObservations.test.ts +106 -0
  259. package/src/db/tables/fundingDepositRequestObservations.ts +99 -0
  260. package/src/db/tables/fundingDeposits.test.ts +138 -0
  261. package/src/db/tables/fundingDeposits.ts +145 -1
  262. package/src/internal/Auth.test.ts +177 -5
  263. package/src/internal/Auth.ts +48 -18
  264. package/src/internal/Cache.test.ts +37 -3
  265. package/src/internal/Cache.ts +1 -1
  266. package/src/internal/EdgeCache.test.ts +7 -7
  267. package/src/internal/EdgeCache.ts +13 -4
  268. package/src/internal/IpAllowlist.test.ts +52 -0
  269. package/src/internal/IpAllowlist.ts +39 -0
  270. package/src/internal/Log.test.ts +7 -1
  271. package/src/internal/OpenApi.ts +1 -1
  272. package/src/internal/Tidx.test.ts +28 -0
  273. package/src/internal/Tidx.ts +19 -3
  274. package/src/internal/Viem.test.ts +28 -0
  275. package/src/internal/Viem.ts +21 -5
  276. package/src/internal/funding/Deposit.ts +74 -5
  277. package/src/internal/funding/Evidence.test.ts +2 -2
  278. package/src/internal/funding/Evidence.ts +4 -9
  279. package/src/internal/funding/Provider.ts +115 -0
  280. package/src/internal/funding/Reconciliation.local.test.ts +7 -0
  281. package/src/internal/funding/Reconciliation.test.ts +1052 -35
  282. package/src/internal/funding/Reconciliation.ts +328 -56
  283. package/src/internal/funding/SourceObservation.test.ts +301 -0
  284. package/src/internal/funding/SourceObservation.ts +267 -0
  285. package/src/internal/funding/Subsidy.ts +2 -2
  286. package/src/internal/funding/index.test.ts +1 -0
  287. package/src/internal/funding/index.ts +1 -0
  288. package/src/internal/funding/providers/relay.test.ts +94 -4
  289. package/src/internal/funding/providers/relay.ts +528 -27
  290. package/dist/apps/data/routes/funding.d.ts.map +0 -1
  291. package/dist/apps/data/routes/funding.js +0 -1557
  292. package/dist/apps/data/routes/funding.js.map +0 -1
  293. package/src/apps/data/routes/funding.test.ts +0 -2994
  294. package/src/apps/data/routes/funding.ts +0 -1821
@@ -1,6 +1,6 @@
1
1
  import { Hono } from 'hono';
2
2
  import { Value as core_Value } from 'ox';
3
- import { ContractFunctionExecutionError, ContractFunctionRevertedError, ContractFunctionZeroDataError, } from 'viem';
3
+ import { ContractFunctionExecutionError, ContractFunctionRevertedError, ContractFunctionZeroDataError, zeroAddress, } from 'viem';
4
4
  import * as z from 'zod/mini';
5
5
  import * as Db from '../../../db/Db.js';
6
6
  import * as core_EarnVaults from '../../../db/tables/earnVaults.js';
@@ -13,6 +13,7 @@ import * as OpenApi from '../../../internal/OpenApi.js';
13
13
  import * as Response from '../../../internal/Response.js';
14
14
  import * as Schema from '../../../internal/Schema.js';
15
15
  import * as Store from '../../../internal/Store.js';
16
+ import * as Tidx from '../../../internal/Tidx.js';
16
17
  import * as Timing from '../../../internal/Timing.js';
17
18
  import * as Ttl from '../../../internal/Ttl.js';
18
19
  import * as Value from '../../../internal/Value.js';
@@ -21,6 +22,13 @@ import * as FxOracle from '../FxOracle.js';
21
22
  import * as Tokens from './tokens.js';
22
23
  import * as Valuation from './valuation.js';
23
24
  const deployedSignature = 'event EarnStackDeployed(address indexed earnVault,address indexed earnShare,address indexed earnFees,address engine,address asset,address owner,bytes32 deploymentId,address emergencyGuardian,address asyncJanitor,uint8 migrationMode,bytes32 earnShareSalt,bytes32 controlConfigHash,bytes32 feeConfigHash,bytes32 earnFeesSalt)';
25
+ const depositedSignature = 'event Deposited(address indexed caller,address indexed receiver,uint256 assets,uint256 earnShares)';
26
+ const redeemedSignature = 'event Redeemed(address indexed caller,address indexed receiver,uint256 earnShares,uint256 assets)';
27
+ const withdrewExactSignature = 'event WithdrewExact(address indexed caller,address indexed receiver,uint256 assets,uint256 earnSharesBurned)';
28
+ const redeemFinalizedSignature = 'event RedeemFinalized(bytes32 indexed requestId,address indexed receiver,uint256 earnShares,address asset,uint256 assets)';
29
+ const redeemCancelledSignature = 'event RedeemCancelled(bytes32 indexed requestId,address indexed receiver,uint256 earnShares)';
30
+ const redeemRequestedSignature = 'event RedeemRequested(bytes32 indexed requestId,address indexed requester,address indexed receiver,uint256 earnShares)';
31
+ const venueSharesDepositedSignature = 'event VenueSharesDeposited(address indexed caller,address indexed receiver,uint256 requestedVenueShares,uint256 receivedVenueShares,uint256 earnShares)';
24
32
  const maxScannedDeployments = 250;
25
33
  const scanLimit = 50;
26
34
  /** Vault TVL is reported in USD only; the API exposes no denomination parameter. */
@@ -155,6 +163,53 @@ export var schema;
155
163
  shareToken: Schema.tokenAddress('0x20c000000000000000000000300e14ab91a10769').check(z.describe('TIP-20 token representing Earn shares.')),
156
164
  value: Schema.DecimalString.check(z.describe('Current asset value of this account’s Earn shares, including fees, in asset base units.'), z.meta({ examples: ['100000000'] })),
157
165
  });
166
+ const earningsBase = z.strictObject({
167
+ account: Schema.Address.check(z.describe('Account whose vault earnings were calculated.'), z.meta({ examples: ['0x68f94cfca22e5969c0553bbeab00a2acde88939b'] })),
168
+ assetToken: Schema.TokenAddress.check(z.describe('TIP-20 asset token accepted by the vault.'), z.meta({ examples: ['0x20c000000000000000000000ff04042ee92fd449'] })),
169
+ currentValue: Schema.DecimalString.check(z.describe('Asset value of the account’s active Earn shares at the latest indexed block, in asset base units.'), z.meta({ examples: ['600000'] })),
170
+ id: Schema.Address.check(z.describe('Stable resource ID for these vault earnings, equal to the account address.'), z.meta({ examples: ['0x68f94cfca22e5969c0553bbeab00a2acde88939b'] })),
171
+ });
172
+ const earningsPeriod = z
173
+ .enum(['active', 'lifetime'])
174
+ .check(z.describe('Earnings period to calculate.'), z.meta({ examples: ['lifetime'] }));
175
+ const earnings = z.union([
176
+ z.extend(earningsBase, {
177
+ lifetimeEarnings: z
178
+ .string()
179
+ .check(z.regex(/^-?\d+$/), z.describe('Current share value plus completed redemptions, exact withdrawals, and finalized async assets, minus asset deposits, at the latest indexed block.'), z.meta({ examples: ['0'] })),
180
+ period: z
181
+ .literal('lifetime')
182
+ .check(z.describe('Returns lifetime net asset earnings.'), z.meta({ examples: ['lifetime'] })),
183
+ status: z
184
+ .literal('complete')
185
+ .check(z.describe('Earnings include a complete asset-denominated cost basis.'), z.meta({ examples: ['complete'] })),
186
+ }),
187
+ z.extend(earningsBase, {
188
+ activeEarnings: z
189
+ .string()
190
+ .check(z.regex(/^-?\d+$/), z.describe('Current share value minus the weighted-average asset cost basis of shares still held, at the latest indexed block.'), z.meta({ examples: ['0'] })),
191
+ period: z
192
+ .literal('active')
193
+ .check(z.describe('Returns earnings on shares still held.'), z.meta({ examples: ['active'] })),
194
+ status: z
195
+ .literal('complete')
196
+ .check(z.describe('Earnings include a complete asset-denominated cost basis.'), z.meta({ examples: ['complete'] })),
197
+ }),
198
+ z.extend(earningsBase, {
199
+ period: earningsPeriod,
200
+ status: z
201
+ .literal('incomplete_cost_basis')
202
+ .check(z.describe('Earnings are unavailable when indexed activity cannot reconstruct the remaining asset cost basis.'), z.meta({ examples: ['incomplete_cost_basis'] })),
203
+ }),
204
+ z.extend(earningsBase, {
205
+ period: z
206
+ .literal('lifetime')
207
+ .check(z.describe('Returns lifetime net asset earnings.'), z.meta({ examples: ['lifetime'] })),
208
+ status: z
209
+ .literal('pending_redemption')
210
+ .check(z.describe('Earnings are unavailable while an async redemption remains open.'), z.meta({ examples: ['pending_redemption'] })),
211
+ }),
212
+ ]);
158
213
  const meta = z
159
214
  .object({
160
215
  valuation: z
@@ -251,6 +306,26 @@ export var schema;
251
306
  /** Current asset and Earn-share state for one account in one vault. */
252
307
  getEarnVaultPosition.Response = Schema.describe(position, 'Current asset and Earn-share balances, allowances, and asset value for an account in one Earn vault.');
253
308
  })(getEarnVaultPosition = schema.getEarnVaultPosition || (schema.getEarnVaultPosition = {}));
309
+ /** Schemas for the getEarnVaultEarnings operation. */
310
+ let getEarnVaultEarnings;
311
+ (function (getEarnVaultEarnings) {
312
+ /** Path parameters identifying the Earn vault and account. */
313
+ getEarnVaultEarnings.Params = z
314
+ .strictObject({
315
+ address: Schema.Address.check(z.describe('Account whose vault earnings to read.')),
316
+ vaultId: Schema.address('0xf4ae63687d6753a78e7f551d2eda1d0d31a5ea3a').check(z.describe('Earn vault contract address.')),
317
+ })
318
+ .check(z.describe('Path parameters identifying an Earn vault account.'));
319
+ /** Query parameters selecting the chain containing the vault. */
320
+ getEarnVaultEarnings.Query = z
321
+ .strictObject({
322
+ chainId: Schema.ChainIdQuery,
323
+ period: z._default(earningsPeriod, 'lifetime'),
324
+ })
325
+ .check(z.describe('Query parameters selecting an Earn vault account.'));
326
+ /** Earnings for one account and period in one Earn vault. */
327
+ getEarnVaultEarnings.Response = Schema.describe(earnings, 'Indexed asset value and cost-basis-aware earnings for an account in one Earn vault.');
328
+ })(getEarnVaultEarnings = schema.getEarnVaultEarnings || (schema.getEarnVaultEarnings = {}));
254
329
  })(schema || (schema = {}));
255
330
  /** Creates the public Earn-vault handlers. */
256
331
  export function earn(options = {}) {
@@ -269,7 +344,7 @@ export function earn(options = {}) {
269
344
  schema: schema.getEarnVaults.Response,
270
345
  },
271
346
  }),
272
- summary: 'List Earn vaults',
347
+ summary: 'List vaults',
273
348
  tags: ['Earn'],
274
349
  }),
275
350
  // Live state and rate enrichment are embedded, so every vault read caches
@@ -363,7 +438,7 @@ export function earn(options = {}) {
363
438
  schema: schema.getEarnVaultPosition.Response,
364
439
  },
365
440
  }),
366
- summary: 'Get vault position',
441
+ summary: 'Get account position',
367
442
  tags: ['Earn'],
368
443
  }), Cache.response({
369
444
  cacheControl: Cache.policies.state,
@@ -427,6 +502,94 @@ export function earn(options = {}) {
427
502
  }
428
503
  return Response.upstream(c, cause);
429
504
  }
505
+ })
506
+ .get('/v1/earn/vaults/:vaultId/earnings/:address', Auth.policy({ apiKey: { scopes: ['data:read'] }, mpp: true, public: true }), OpenApi.validate('param', schema.getEarnVaultEarnings.Params, {
507
+ code: 'earnings_invalid',
508
+ message: 'Invalid vault earnings',
509
+ }), OpenApi.validate('query', schema.getEarnVaultEarnings.Query, {
510
+ code: 'query_invalid',
511
+ message: 'Invalid query parameters',
512
+ }), OpenApi.describeRoute({
513
+ description: 'Gets an account’s indexed asset value and earnings for lifetime history or shares still held.',
514
+ operationId: 'getEarnVaultEarnings',
515
+ responses: OpenApi.responses({
516
+ errors: {
517
+ 400: {
518
+ codes: [
519
+ 'chain_id_invalid',
520
+ 'chain_id_unsupported',
521
+ 'earnings_invalid',
522
+ 'query_invalid',
523
+ ],
524
+ },
525
+ 404: {
526
+ codes: ['earn_vault_not_found'],
527
+ description: 'No compatible Earn vault was found at this address.',
528
+ },
529
+ 502: 'Could not read the Earn vault earnings.',
530
+ },
531
+ success: {
532
+ description: 'Cost-basis-aware earnings for one account in one vault.',
533
+ schema: schema.getEarnVaultEarnings.Response,
534
+ },
535
+ }),
536
+ summary: 'Get vault earnings',
537
+ tags: ['Earn'],
538
+ }), Cache.response({
539
+ cacheControl: Cache.policies.state,
540
+ key: (c) => Cache.urlKey(c, schema.getEarnVaultEarnings.Query),
541
+ name: 'tempo-api:earn-vault-earnings:v2',
542
+ }), async (c) => {
543
+ if (Auth.narrowAccess)
544
+ return Auth.paidAccessError(c);
545
+ if (OpenApi.narrowValidation)
546
+ return Response.error(c, {
547
+ code: 'chain_id_invalid',
548
+ message: 'Invalid chain id',
549
+ status: 400,
550
+ });
551
+ if (OpenApi.narrowValidation)
552
+ return Response.error(c, {
553
+ code: 'chain_id_unsupported',
554
+ message: 'Unsupported chain id',
555
+ status: 400,
556
+ });
557
+ if (OpenApi.narrowValidation)
558
+ return OpenApi.validationError(c, {
559
+ code: 'earnings_invalid',
560
+ message: 'Invalid request parameters',
561
+ });
562
+ if (OpenApi.narrowValidation)
563
+ return OpenApi.validationError(c, {
564
+ code: 'query_invalid',
565
+ message: 'Invalid query parameters',
566
+ });
567
+ const { address, vaultId } = c.req.valid('param');
568
+ const query = c.req.valid('query');
569
+ const chainId = query.chainId ?? c.get('chainId');
570
+ try {
571
+ const data = await getVaultEarnings(c, {
572
+ account: address,
573
+ chainId,
574
+ period: query.period,
575
+ vault: vaultId,
576
+ });
577
+ return c.json(Response.validated(schema.getEarnVaultEarnings.Response, data), 200);
578
+ }
579
+ catch (cause) {
580
+ try {
581
+ await resolveVaultDiscovery(c, { chainId, include: [], vaultAddress: vaultId });
582
+ }
583
+ catch (vaultCause) {
584
+ if (isIncompatible(vaultCause))
585
+ return Response.error(c, {
586
+ code: 'earn_vault_not_found',
587
+ message: 'Earn vault not found',
588
+ status: 404,
589
+ });
590
+ }
591
+ return Response.upstream(c, cause);
592
+ }
430
593
  })
431
594
  .get('/v1/earn/vaults/:vaultId', Auth.policy({ apiKey: { scopes: ['data:read'] }, mpp: true, public: true }), OpenApi.validate('param', schema.getEarnVault.Params, {
432
595
  code: 'vault_id_invalid',
@@ -450,7 +613,7 @@ export function earn(options = {}) {
450
613
  schema: schema.getEarnVault.Response,
451
614
  },
452
615
  }),
453
- summary: 'Get Earn vault',
616
+ summary: 'Get vault',
454
617
  tags: ['Earn'],
455
618
  }), Cache.response({
456
619
  cacheControl: Cache.policies.state,
@@ -493,6 +656,470 @@ export function earn(options = {}) {
493
656
  }
494
657
  });
495
658
  }
659
+ /** Reads one account's indexed value and returns earnings when the history is complete. */
660
+ export async function getVaultEarnings(c, options) {
661
+ const client = c.get('getClient')(options.chainId);
662
+ const tidx = c.get('getTidx')(options.chainId);
663
+ const blockNumber = await getLatestIndexedBlockNumber(tidx);
664
+ const position = client.earn.getPosition({
665
+ account: options.account,
666
+ blockNumber: BigInt(blockNumber),
667
+ vault: options.vault,
668
+ });
669
+ if (options.period === 'active') {
670
+ const current = await position;
671
+ const base = {
672
+ account: options.account,
673
+ assetToken: current.assetToken,
674
+ currentValue: current.value.toString(),
675
+ id: options.account,
676
+ period: options.period,
677
+ };
678
+ const activeCostBasis = await getActiveCostBasis(tidx, {
679
+ account: options.account,
680
+ blockNumber,
681
+ shareBalance: current.shareBalance,
682
+ shareToken: current.shareToken,
683
+ vault: options.vault,
684
+ });
685
+ if (activeCostBasis === undefined)
686
+ return { ...base, status: 'incomplete_cost_basis' };
687
+ return {
688
+ ...base,
689
+ activeEarnings: (current.value - activeCostBasis).toString(),
690
+ status: 'complete',
691
+ };
692
+ }
693
+ const [history, current] = await Promise.all([
694
+ getVaultEarningsHistory(tidx, {
695
+ account: options.account,
696
+ blockNumber,
697
+ vault: options.vault,
698
+ }),
699
+ position,
700
+ ]);
701
+ const externalShareTransfer = await hasExternalShareTransfer(tidx, {
702
+ account: options.account,
703
+ blockNumber,
704
+ shareToken: current.shareToken,
705
+ vault: options.vault,
706
+ });
707
+ const base = {
708
+ account: options.account,
709
+ assetToken: current.assetToken,
710
+ currentValue: current.value.toString(),
711
+ id: options.account,
712
+ period: options.period,
713
+ };
714
+ if (history.incompleteCostBasis || externalShareTransfer)
715
+ return { ...base, status: 'incomplete_cost_basis' };
716
+ if (history.pendingRedemption)
717
+ return { ...base, status: 'pending_redemption' };
718
+ const lifetimeEarnings = current.value + history.redeemed + history.withdrewExact + history.finalized - history.deposited;
719
+ return { ...base, lifetimeEarnings: lifetimeEarnings.toString(), status: 'complete' };
720
+ }
721
+ /** Reads the latest block whose indexed logs back the earnings calculation. */
722
+ async function getLatestIndexedBlockNumber(tidx) {
723
+ const result = await tidx.fetch({
724
+ engine: 'clickhouse',
725
+ query: 'SELECT num FROM blocks ORDER BY num DESC LIMIT 1',
726
+ });
727
+ const blockNumber = Value.toNumber(result.rows[0]?.['num']);
728
+ if (blockNumber === undefined)
729
+ throw new Error('TIDX returned no indexed block.');
730
+ return blockNumber;
731
+ }
732
+ /** Reads the indexed cash flows and exceptional states behind one earnings calculation. */
733
+ async function getVaultEarningsHistory(tidx, options) {
734
+ const result = await tidx.fetch({
735
+ engine: 'clickhouse',
736
+ query: `
737
+ SELECT
738
+ (
739
+ SELECT toString(sum(toUInt256(assets)))
740
+ FROM Deposited
741
+ WHERE address = '${options.vault}'
742
+ AND receiver = '${options.account}'
743
+ AND block_num <= ${options.blockNumber}
744
+ ) AS deposited_assets,
745
+ (
746
+ SELECT toString(sum(toUInt256(finalized.assets)))
747
+ FROM RedeemFinalized AS finalized
748
+ INNER JOIN RedeemRequested AS requested
749
+ ON requested.address = finalized.address
750
+ AND requested."requestId" = finalized."requestId"
751
+ WHERE finalized.address = '${options.vault}'
752
+ AND requested.requester = '${options.account}'
753
+ AND finalized.block_num <= ${options.blockNumber}
754
+ AND requested.block_num <= ${options.blockNumber}
755
+ ) AS finalized_assets,
756
+ (
757
+ SELECT count()
758
+ FROM RedeemRequested AS requested
759
+ LEFT ANTI JOIN RedeemFinalized AS finalized
760
+ ON finalized.address = requested.address
761
+ AND finalized."requestId" = requested."requestId"
762
+ AND finalized.block_num <= ${options.blockNumber}
763
+ LEFT ANTI JOIN RedeemCancelled AS cancelled
764
+ ON cancelled.address = requested.address
765
+ AND cancelled."requestId" = requested."requestId"
766
+ AND cancelled.block_num <= ${options.blockNumber}
767
+ WHERE requested.address = '${options.vault}'
768
+ AND requested.requester = '${options.account}'
769
+ AND requested.block_num <= ${options.blockNumber}
770
+ ) AS pending_redemptions,
771
+ (
772
+ SELECT toString(sum(toUInt256(assets)))
773
+ FROM Redeemed
774
+ WHERE address = '${options.vault}'
775
+ AND caller = '${options.account}'
776
+ AND block_num <= ${options.blockNumber}
777
+ ) AS redeemed_assets,
778
+ (
779
+ SELECT count()
780
+ FROM RedeemCancelled AS cancelled
781
+ INNER JOIN RedeemRequested AS requested
782
+ ON requested.address = cancelled.address
783
+ AND requested."requestId" = cancelled."requestId"
784
+ WHERE cancelled.address = '${options.vault}'
785
+ AND cancelled.block_num <= ${options.blockNumber}
786
+ AND requested.block_num <= ${options.blockNumber}
787
+ AND requested.requester != cancelled.receiver
788
+ AND (
789
+ requested.requester = '${options.account}'
790
+ OR cancelled.receiver = '${options.account}'
791
+ )
792
+ ) AS transferred_cancellations,
793
+ (
794
+ SELECT count()
795
+ FROM VenueSharesDeposited
796
+ WHERE address = '${options.vault}'
797
+ AND receiver = '${options.account}'
798
+ AND block_num <= ${options.blockNumber}
799
+ ) AS venue_deposits,
800
+ (
801
+ SELECT toString(sum(toUInt256(assets)))
802
+ FROM WithdrewExact
803
+ WHERE address = '${options.vault}'
804
+ AND caller = '${options.account}'
805
+ AND block_num <= ${options.blockNumber}
806
+ ) AS withdrew_exact
807
+ `,
808
+ signatures: [
809
+ depositedSignature,
810
+ redeemCancelledSignature,
811
+ redeemFinalizedSignature,
812
+ redeemRequestedSignature,
813
+ redeemedSignature,
814
+ venueSharesDepositedSignature,
815
+ withdrewExactSignature,
816
+ ],
817
+ });
818
+ const row = result.rows[0];
819
+ const deposited = Value.toIntegerString(row?.['deposited_assets']);
820
+ const finalized = Value.toIntegerString(row?.['finalized_assets']);
821
+ const pendingRedemptions = Value.toNumber(row?.['pending_redemptions']);
822
+ const redeemed = Value.toIntegerString(row?.['redeemed_assets']);
823
+ const transferredCancellations = Value.toNumber(row?.['transferred_cancellations']);
824
+ const venueDeposits = Value.toNumber(row?.['venue_deposits']);
825
+ const withdrewExact = Value.toIntegerString(row?.['withdrew_exact']);
826
+ if (deposited === undefined ||
827
+ finalized === undefined ||
828
+ pendingRedemptions === undefined ||
829
+ redeemed === undefined ||
830
+ transferredCancellations === undefined ||
831
+ venueDeposits === undefined ||
832
+ withdrewExact === undefined)
833
+ throw new Error('TIDX returned invalid Earn earnings history.');
834
+ return {
835
+ deposited: BigInt(deposited),
836
+ finalized: BigInt(finalized),
837
+ incompleteCostBasis: transferredCancellations > 0 || venueDeposits > 0,
838
+ pendingRedemption: pendingRedemptions > 0,
839
+ redeemed: BigInt(redeemed),
840
+ withdrewExact: BigInt(withdrewExact),
841
+ };
842
+ }
843
+ /** Returns whether an account sent or received Earn shares outside known vault flows. */
844
+ async function hasExternalShareTransfer(tidx, options) {
845
+ // Vault exits pull shares into the vault before burning. Reconcile counts by transaction and amount so unmatched direct sends remain external.
846
+ const result = await tidx.fetch({
847
+ engine: 'clickhouse',
848
+ query: `
849
+ SELECT
850
+ (
851
+ SELECT count()
852
+ FROM token_transfers
853
+ WHERE token = '${options.shareToken.toLowerCase()}'
854
+ AND block_num <= ${options.blockNumber}
855
+ AND (
856
+ ("from" = '${options.account}' AND "to" != '${options.vault}')
857
+ OR ("to" = '${options.account}' AND "from" != '${zeroAddress}')
858
+ )
859
+ ) + (
860
+ SELECT count()
861
+ FROM (
862
+ SELECT tx_hash, toUInt256(amount) AS amount, count() AS transfer_count
863
+ FROM token_transfers
864
+ WHERE token = '${options.shareToken.toLowerCase()}'
865
+ AND "from" = '${options.account}'
866
+ AND "to" = '${options.vault}'
867
+ AND block_num <= ${options.blockNumber}
868
+ GROUP BY tx_hash, amount
869
+ ) AS candidate
870
+ LEFT JOIN (
871
+ SELECT tx_hash, amount, count() AS exit_count
872
+ FROM (
873
+ SELECT tx_hash, toUInt256(earnShares) AS amount
874
+ FROM Redeemed
875
+ WHERE address = '${options.vault}'
876
+ AND caller = '${options.account}'
877
+ AND block_num <= ${options.blockNumber}
878
+ UNION ALL
879
+ SELECT tx_hash, toUInt256(earnShares) AS amount
880
+ FROM RedeemRequested
881
+ WHERE address = '${options.vault}'
882
+ AND requester = '${options.account}'
883
+ AND block_num <= ${options.blockNumber}
884
+ UNION ALL
885
+ SELECT tx_hash, toUInt256(earnSharesBurned) AS amount
886
+ FROM WithdrewExact
887
+ WHERE address = '${options.vault}'
888
+ AND caller = '${options.account}'
889
+ AND block_num <= ${options.blockNumber}
890
+ ) AS protocol_exit
891
+ GROUP BY tx_hash, amount
892
+ ) AS matched
893
+ ON matched.tx_hash = candidate.tx_hash AND matched.amount = candidate.amount
894
+ WHERE candidate.transfer_count > coalesce(matched.exit_count, 0)
895
+ ) AS count
896
+ `,
897
+ signatures: [redeemedSignature, redeemRequestedSignature, withdrewExactSignature],
898
+ });
899
+ const count = Value.toNumber(result.rows[0]?.['count']);
900
+ if (count === undefined)
901
+ throw new Error('TIDX returned an invalid Earn-share transfer count.');
902
+ return count > 0;
903
+ }
904
+ /** Calculates the asset cost basis attached to an account's remaining Earn shares. */
905
+ export function calculateActiveCostBasis(options) {
906
+ const requests = new Map();
907
+ let costBasis = 0n;
908
+ let shares = 0n;
909
+ const remove = (burned) => {
910
+ if (burned > shares || shares === 0n)
911
+ return undefined;
912
+ const removed = (() => {
913
+ if (costBasis === undefined)
914
+ return undefined;
915
+ return burned === shares ? costBasis : (costBasis * burned) / shares;
916
+ })();
917
+ if (burned === shares)
918
+ costBasis = 0n;
919
+ else if (costBasis !== undefined && removed !== undefined)
920
+ costBasis -= removed;
921
+ shares -= burned;
922
+ return { costBasis: removed };
923
+ };
924
+ for (const action of options.actions) {
925
+ if (action.kind === 'deposit') {
926
+ if (costBasis !== undefined)
927
+ costBasis += action.assets;
928
+ shares += action.shares;
929
+ continue;
930
+ }
931
+ if (action.kind === 'unknown') {
932
+ costBasis = undefined;
933
+ shares += action.shares;
934
+ continue;
935
+ }
936
+ if (action.kind === 'cancel') {
937
+ const restored = requests.get(action.requestId);
938
+ if (restored === undefined || restored.shares !== action.shares)
939
+ return undefined;
940
+ if (costBasis === undefined || restored.costBasis === undefined)
941
+ costBasis = undefined;
942
+ else
943
+ costBasis += restored.costBasis;
944
+ shares += restored.shares;
945
+ requests.delete(action.requestId);
946
+ continue;
947
+ }
948
+ const removed = remove(action.shares);
949
+ if (removed === undefined)
950
+ return undefined;
951
+ if (action.kind === 'request')
952
+ requests.set(action.requestId, { costBasis: removed.costBasis, shares: action.shares });
953
+ }
954
+ return shares === options.shareBalance && costBasis !== undefined ? costBasis : undefined;
955
+ }
956
+ /** Reads the active asset cost basis for shares held at one indexed block. */
957
+ async function getActiveCostBasis(tidx, options) {
958
+ const result = await tidx.fetch({
959
+ engine: 'clickhouse',
960
+ query: `
961
+ SELECT kind, request_id, shares, assets
962
+ FROM (
963
+ SELECT
964
+ 'deposit' AS kind,
965
+ block_num,
966
+ log_idx,
967
+ '' AS request_id,
968
+ toString(toUInt256(earnShares)) AS shares,
969
+ toString(toUInt256(assets)) AS assets
970
+ FROM Deposited
971
+ WHERE address = '${options.vault}'
972
+ AND receiver = '${options.account}'
973
+ AND block_num <= ${options.blockNumber}
974
+ UNION ALL
975
+ SELECT
976
+ 'redeem' AS kind,
977
+ block_num,
978
+ log_idx,
979
+ '' AS request_id,
980
+ toString(toUInt256(earnShares)) AS shares,
981
+ '0' AS assets
982
+ FROM Redeemed
983
+ WHERE address = '${options.vault}'
984
+ AND caller = '${options.account}'
985
+ AND block_num <= ${options.blockNumber}
986
+ UNION ALL
987
+ SELECT
988
+ 'redeem' AS kind,
989
+ block_num,
990
+ log_idx,
991
+ '' AS request_id,
992
+ toString(toUInt256(earnSharesBurned)) AS shares,
993
+ '0' AS assets
994
+ FROM WithdrewExact
995
+ WHERE address = '${options.vault}'
996
+ AND caller = '${options.account}'
997
+ AND block_num <= ${options.blockNumber}
998
+ UNION ALL
999
+ SELECT
1000
+ 'request' AS kind,
1001
+ block_num,
1002
+ log_idx,
1003
+ "requestId" AS request_id,
1004
+ toString(toUInt256(earnShares)) AS shares,
1005
+ '0' AS assets
1006
+ FROM RedeemRequested
1007
+ WHERE address = '${options.vault}'
1008
+ AND requester = '${options.account}'
1009
+ AND block_num <= ${options.blockNumber}
1010
+ UNION ALL
1011
+ SELECT
1012
+ 'cancel' AS kind,
1013
+ cancelled.block_num AS block_num,
1014
+ cancelled.log_idx AS log_idx,
1015
+ cancelled."requestId" AS request_id,
1016
+ toString(toUInt256(cancelled.earnShares)) AS shares,
1017
+ '0' AS assets
1018
+ FROM RedeemCancelled AS cancelled
1019
+ INNER JOIN RedeemRequested AS requested
1020
+ ON requested.address = cancelled.address
1021
+ AND requested."requestId" = cancelled."requestId"
1022
+ WHERE cancelled.address = '${options.vault}'
1023
+ AND requested.requester = '${options.account}'
1024
+ AND cancelled.receiver = '${options.account}'
1025
+ AND cancelled.block_num <= ${options.blockNumber}
1026
+ AND requested.block_num <= ${options.blockNumber}
1027
+ UNION ALL
1028
+ SELECT
1029
+ 'unknown' AS kind,
1030
+ block_num,
1031
+ log_idx,
1032
+ '' AS request_id,
1033
+ toString(toUInt256(earnShares)) AS shares,
1034
+ '0' AS assets
1035
+ FROM VenueSharesDeposited
1036
+ WHERE address = '${options.vault}'
1037
+ AND receiver = '${options.account}'
1038
+ AND block_num <= ${options.blockNumber}
1039
+ UNION ALL
1040
+ SELECT
1041
+ 'unknown' AS kind,
1042
+ block_num,
1043
+ log_idx,
1044
+ '' AS request_id,
1045
+ toString(toUInt256(amount)) AS shares,
1046
+ '0' AS assets
1047
+ FROM token_transfers
1048
+ WHERE token = '${options.shareToken.toLowerCase()}'
1049
+ AND "to" = '${options.account}'
1050
+ AND "from" != '${zeroAddress}'
1051
+ AND "from" != '${options.vault}'
1052
+ AND block_num <= ${options.blockNumber}
1053
+ UNION ALL
1054
+ SELECT
1055
+ 'redeem' AS kind,
1056
+ block_num,
1057
+ log_idx,
1058
+ '' AS request_id,
1059
+ toString(toUInt256(amount)) AS shares,
1060
+ '0' AS assets
1061
+ FROM token_transfers
1062
+ WHERE token = '${options.shareToken.toLowerCase()}'
1063
+ AND "from" = '${options.account}'
1064
+ AND "to" != '${options.vault}'
1065
+ AND block_num <= ${options.blockNumber}
1066
+ ) AS actions
1067
+ ORDER BY block_num, log_idx
1068
+ `,
1069
+ signatures: [
1070
+ depositedSignature,
1071
+ redeemCancelledSignature,
1072
+ redeemRequestedSignature,
1073
+ redeemedSignature,
1074
+ venueSharesDepositedSignature,
1075
+ withdrewExactSignature,
1076
+ ],
1077
+ });
1078
+ const actions = [];
1079
+ for (const row of result.rows) {
1080
+ const kind = Value.toText(row['kind']);
1081
+ if (kind === 'deposit') {
1082
+ const assets = Value.toIntegerString(row['assets']);
1083
+ const shares = Value.toIntegerString(row['shares']);
1084
+ if (assets === undefined || shares === undefined)
1085
+ return undefined;
1086
+ actions.push({ assets: BigInt(assets), kind, shares: BigInt(shares) });
1087
+ continue;
1088
+ }
1089
+ if (kind === 'redeem') {
1090
+ const shares = Value.toIntegerString(row['shares']);
1091
+ if (shares === undefined)
1092
+ return undefined;
1093
+ actions.push({ kind, shares: BigInt(shares) });
1094
+ continue;
1095
+ }
1096
+ if (kind === 'cancel') {
1097
+ const requestId = Value.toText(row['request_id']);
1098
+ const shares = Value.toIntegerString(row['shares']);
1099
+ if (requestId === undefined || shares === undefined)
1100
+ return undefined;
1101
+ actions.push({ kind, requestId, shares: BigInt(shares) });
1102
+ continue;
1103
+ }
1104
+ if (kind === 'request') {
1105
+ const requestId = Value.toText(row['request_id']);
1106
+ const shares = Value.toIntegerString(row['shares']);
1107
+ if (requestId === undefined || shares === undefined)
1108
+ return undefined;
1109
+ actions.push({ kind, requestId, shares: BigInt(shares) });
1110
+ continue;
1111
+ }
1112
+ if (kind === 'unknown') {
1113
+ const shares = Value.toIntegerString(row['shares']);
1114
+ if (shares === undefined)
1115
+ return undefined;
1116
+ actions.push({ kind, shares: BigInt(shares) });
1117
+ continue;
1118
+ }
1119
+ return undefined;
1120
+ }
1121
+ return calculateActiveCostBasis({ actions, shareBalance: options.shareBalance });
1122
+ }
496
1123
  /** Lists compatible deployed Earn vaults. */
497
1124
  export async function listVaults(c, options) {
498
1125
  const db = Db.get(c.get('dbCached'));