tapimo 0.8.0 → 0.9.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.
- package/dist/App.d.ts +2095 -2111
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +0 -1
- package/dist/App.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +166 -166
- package/dist/apps/data/App.d.ts +4084 -3845
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +270 -270
- package/dist/apps/data/routes/addresses.d.ts +248 -17
- package/dist/apps/data/routes/addresses.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.d.ts +272 -2
- package/dist/apps/data/routes/balances.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.js +114 -2
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/blocks.d.ts +123 -123
- package/dist/apps/data/routes/earn.d.ts +65 -3
- package/dist/apps/data/routes/earn.d.ts.map +1 -1
- package/dist/apps/data/routes/earn.js +259 -14
- package/dist/apps/data/routes/earn.js.map +1 -1
- package/dist/apps/data/routes/rpc.d.ts +31 -31
- package/dist/apps/data/routes/tokens.d.ts +454 -454
- package/dist/apps/data/routes/transfers.d.ts +81 -81
- package/dist/apps/funding/App.d.ts +40 -299
- package/dist/apps/funding/App.d.ts.map +1 -1
- package/dist/apps/funding/App.js +20 -5
- package/dist/apps/funding/App.js.map +1 -1
- package/dist/apps/funding/routes/deposit-addresses.d.ts +43 -434
- package/dist/apps/funding/routes/deposit-addresses.d.ts.map +1 -1
- package/dist/apps/funding/routes/deposit-addresses.js +21 -103
- package/dist/apps/funding/routes/deposit-addresses.js.map +1 -1
- package/dist/apps/funding/routes/quotes.d.ts +89 -89
- package/dist/apps/funding/routes/transfers.js +5 -5
- package/dist/apps/funding/routes/transfers.js.map +1 -1
- package/dist/apps/management/routes/invitations.d.ts +134 -134
- package/dist/apps/management/routes/orgs.d.ts +98 -98
- package/dist/apps/management/routes/verified-token-requests.d.ts +83 -83
- package/dist/apps/mpp/App.d.ts +44 -44
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +8 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/tables/fundingDeposits.d.ts +18 -1
- package/dist/db/tables/fundingDeposits.d.ts.map +1 -1
- package/dist/db/tables/fundingDeposits.js +46 -2
- package/dist/db/tables/fundingDeposits.js.map +1 -1
- package/dist/internal/Auth.d.ts +4 -0
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +11 -2
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/funding/Provider.d.ts +6 -6
- package/dist/internal/funding/Provider.d.ts.map +1 -1
- package/dist/internal/funding/Reconciliation.d.ts.map +1 -1
- package/dist/internal/funding/Reconciliation.js +101 -16
- package/dist/internal/funding/Reconciliation.js.map +1 -1
- package/dist/internal/funding/providers/relay.d.ts.map +1 -1
- package/dist/internal/funding/providers/relay.js +6 -2
- package/dist/internal/funding/providers/relay.js.map +1 -1
- package/package.json +1 -1
- package/src/App.test.ts +32 -0
- package/src/App.ts +4 -1
- package/src/Client.test-d.ts +56 -33
- package/src/apps/composition.test.ts +39 -10
- package/src/apps/data/routes/balances.test.ts +42 -0
- package/src/apps/data/routes/balances.ts +218 -85
- package/src/apps/data/routes/earn.test.ts +89 -9
- package/src/apps/data/routes/earn.ts +355 -14
- package/src/apps/funding/App.ts +20 -5
- package/src/apps/funding/routes/deposit-addresses.test.ts +43 -22
- package/src/apps/funding/routes/deposit-addresses.ts +34 -117
- package/src/apps/funding/routes/transfers.test.ts +6 -25
- package/src/apps/funding/routes/transfers.ts +5 -5
- package/src/db/Db.ts +9 -0
- package/src/db/tables/fundingDeposits.test.ts +101 -0
- package/src/db/tables/fundingDeposits.ts +71 -2
- package/src/internal/Auth.test.ts +28 -0
- package/src/internal/Auth.ts +15 -1
- package/src/internal/funding/Provider.ts +4 -4
- package/src/internal/funding/Reconciliation.test.ts +292 -54
- package/src/internal/funding/Reconciliation.ts +160 -53
- package/src/internal/funding/SourceObservation.test.ts +2 -2
- package/src/internal/funding/providers/relay.ts +7 -2
|
@@ -56,6 +56,8 @@ const venueSharesDepositedSignature =
|
|
|
56
56
|
|
|
57
57
|
const maxScannedDeployments = 250
|
|
58
58
|
const scanLimit = 50
|
|
59
|
+
/** Block boundary that includes all indexed history. */
|
|
60
|
+
const beforeFirstBlockNumber = -1
|
|
59
61
|
|
|
60
62
|
/** Vault TVL is reported in USD only; the API exposes no denomination parameter. */
|
|
61
63
|
const tvlDenomination = 'USD'
|
|
@@ -345,8 +347,13 @@ export namespace schema {
|
|
|
345
347
|
})
|
|
346
348
|
|
|
347
349
|
const earningsPeriod = z
|
|
348
|
-
.enum(['active', 'lifetime'])
|
|
349
|
-
.check(
|
|
350
|
+
.enum(['30d', 'active', 'lifetime'])
|
|
351
|
+
.check(
|
|
352
|
+
z.describe(
|
|
353
|
+
'Earnings period to calculate: trailing 30 days, shares still held, or lifetime history.',
|
|
354
|
+
),
|
|
355
|
+
z.meta({ examples: ['lifetime'] }),
|
|
356
|
+
)
|
|
350
357
|
|
|
351
358
|
const earnings = z.union([
|
|
352
359
|
z.extend(earningsBase, {
|
|
@@ -395,22 +402,45 @@ export namespace schema {
|
|
|
395
402
|
z.meta({ examples: ['complete'] }),
|
|
396
403
|
),
|
|
397
404
|
}),
|
|
405
|
+
z.extend(earningsBase, {
|
|
406
|
+
period: z
|
|
407
|
+
.literal('30d')
|
|
408
|
+
.check(
|
|
409
|
+
z.describe('Returns cash-flow-adjusted earnings over the trailing 30 days.'),
|
|
410
|
+
z.meta({ examples: ['30d'] }),
|
|
411
|
+
),
|
|
412
|
+
status: z
|
|
413
|
+
.literal('complete')
|
|
414
|
+
.check(
|
|
415
|
+
z.describe('Earnings include a complete asset-denominated cost basis.'),
|
|
416
|
+
z.meta({ examples: ['complete'] }),
|
|
417
|
+
),
|
|
418
|
+
windowEarnings: z
|
|
419
|
+
.string()
|
|
420
|
+
.check(
|
|
421
|
+
z.regex(/^-?\d+$/),
|
|
422
|
+
z.describe(
|
|
423
|
+
'Ending share value plus realized assets, minus deposits and opening share value, over the trailing 30 days.',
|
|
424
|
+
),
|
|
425
|
+
z.meta({ examples: ['0'] }),
|
|
426
|
+
),
|
|
427
|
+
}),
|
|
398
428
|
z.extend(earningsBase, {
|
|
399
429
|
period: earningsPeriod,
|
|
400
430
|
status: z
|
|
401
431
|
.literal('incomplete_cost_basis')
|
|
402
432
|
.check(
|
|
403
433
|
z.describe(
|
|
404
|
-
'Earnings are unavailable when indexed activity cannot reconstruct the
|
|
434
|
+
'Earnings are unavailable when indexed activity cannot reconstruct the asset cost basis for the requested period.',
|
|
405
435
|
),
|
|
406
436
|
z.meta({ examples: ['incomplete_cost_basis'] }),
|
|
407
437
|
),
|
|
408
438
|
}),
|
|
409
439
|
z.extend(earningsBase, {
|
|
410
440
|
period: z
|
|
411
|
-
.
|
|
441
|
+
.enum(['30d', 'lifetime'])
|
|
412
442
|
.check(
|
|
413
|
-
z.describe('
|
|
443
|
+
z.describe('Earnings period with an unresolved async redemption.'),
|
|
414
444
|
z.meta({ examples: ['lifetime'] }),
|
|
415
445
|
),
|
|
416
446
|
status: z
|
|
@@ -791,7 +821,7 @@ export function earn(options: earn.Options = {}) {
|
|
|
791
821
|
}),
|
|
792
822
|
OpenApi.describeRoute({
|
|
793
823
|
description:
|
|
794
|
-
'Gets an account’s indexed asset value and earnings for lifetime history or shares still held.',
|
|
824
|
+
'Gets an account’s indexed asset value and earnings for lifetime history, the trailing 30 days, or shares still held.',
|
|
795
825
|
operationId: 'getEarnVaultEarnings',
|
|
796
826
|
responses: OpenApi.responses({
|
|
797
827
|
errors: {
|
|
@@ -820,7 +850,7 @@ export function earn(options: earn.Options = {}) {
|
|
|
820
850
|
Cache.response<App.Environment>({
|
|
821
851
|
cacheControl: Cache.policies.state,
|
|
822
852
|
key: (c) => Cache.urlKey(c, schema.getEarnVaultEarnings.Query),
|
|
823
|
-
name: 'tempo-api:earn-vault-earnings:
|
|
853
|
+
name: 'tempo-api:earn-vault-earnings:v3',
|
|
824
854
|
}),
|
|
825
855
|
async (c) => {
|
|
826
856
|
if (Auth.narrowAccess) return Auth.paidAccessError(c)
|
|
@@ -962,7 +992,17 @@ export async function getVaultEarnings(
|
|
|
962
992
|
) {
|
|
963
993
|
const client = c.get('getClient')(options.chainId)
|
|
964
994
|
const tidx = c.get('getTidx')(options.chainId)
|
|
965
|
-
const
|
|
995
|
+
const block = await getLatestIndexedBlock(tidx)
|
|
996
|
+
const blockNumber = block.number
|
|
997
|
+
if (options.period === '30d')
|
|
998
|
+
return getWindowVaultEarnings(c, {
|
|
999
|
+
account: options.account,
|
|
1000
|
+
blockNumber,
|
|
1001
|
+
chainId: options.chainId,
|
|
1002
|
+
period: options.period,
|
|
1003
|
+
timestamp: block.timestamp,
|
|
1004
|
+
vault: options.vault,
|
|
1005
|
+
})
|
|
966
1006
|
const position = client.earn.getPosition({
|
|
967
1007
|
account: options.account,
|
|
968
1008
|
blockNumber: BigInt(blockNumber),
|
|
@@ -995,6 +1035,7 @@ export async function getVaultEarnings(
|
|
|
995
1035
|
getVaultEarningsHistory(tidx, {
|
|
996
1036
|
account: options.account,
|
|
997
1037
|
blockNumber,
|
|
1038
|
+
startBlockNumber: beforeFirstBlockNumber,
|
|
998
1039
|
vault: options.vault,
|
|
999
1040
|
}),
|
|
1000
1041
|
position,
|
|
@@ -1003,6 +1044,7 @@ export async function getVaultEarnings(
|
|
|
1003
1044
|
account: options.account,
|
|
1004
1045
|
blockNumber,
|
|
1005
1046
|
shareToken: current.shareToken,
|
|
1047
|
+
startBlockNumber: beforeFirstBlockNumber,
|
|
1006
1048
|
vault: options.vault,
|
|
1007
1049
|
})
|
|
1008
1050
|
const base = {
|
|
@@ -1020,6 +1062,126 @@ export async function getVaultEarnings(
|
|
|
1020
1062
|
return { ...base, lifetimeEarnings: lifetimeEarnings.toString(), status: 'complete' as const }
|
|
1021
1063
|
}
|
|
1022
1064
|
|
|
1065
|
+
/** Reads cash-flow-adjusted earnings over a trailing indexed window. */
|
|
1066
|
+
async function getWindowVaultEarnings(
|
|
1067
|
+
c: Context<App.Environment>,
|
|
1068
|
+
options: getWindowVaultEarnings.Options,
|
|
1069
|
+
) {
|
|
1070
|
+
const client = c.get('getClient')(options.chainId)
|
|
1071
|
+
const tidx = c.get('getTidx')(options.chainId)
|
|
1072
|
+
const [current, startBlockNumber] = await Promise.all([
|
|
1073
|
+
client.earn.getPosition({
|
|
1074
|
+
account: options.account,
|
|
1075
|
+
blockNumber: BigInt(options.blockNumber),
|
|
1076
|
+
vault: options.vault,
|
|
1077
|
+
}),
|
|
1078
|
+
getWindowStartBlockNumber(tidx, { days: 30, timestamp: options.timestamp }),
|
|
1079
|
+
])
|
|
1080
|
+
const [externalShareTransfer, history, opening] = await Promise.all([
|
|
1081
|
+
hasExternalShareTransfer(tidx, {
|
|
1082
|
+
account: options.account,
|
|
1083
|
+
blockNumber: options.blockNumber,
|
|
1084
|
+
shareToken: current.shareToken,
|
|
1085
|
+
startBlockNumber,
|
|
1086
|
+
vault: options.vault,
|
|
1087
|
+
}),
|
|
1088
|
+
getVaultEarningsHistory(tidx, {
|
|
1089
|
+
account: options.account,
|
|
1090
|
+
blockNumber: options.blockNumber,
|
|
1091
|
+
startBlockNumber,
|
|
1092
|
+
vault: options.vault,
|
|
1093
|
+
}),
|
|
1094
|
+
getWindowShareState(tidx, {
|
|
1095
|
+
account: options.account,
|
|
1096
|
+
blockNumber: options.blockNumber,
|
|
1097
|
+
shareToken: current.shareToken,
|
|
1098
|
+
startBlockNumber,
|
|
1099
|
+
vault: options.vault,
|
|
1100
|
+
}),
|
|
1101
|
+
])
|
|
1102
|
+
const base = {
|
|
1103
|
+
account: options.account,
|
|
1104
|
+
assetToken: current.assetToken,
|
|
1105
|
+
currentValue: current.value.toString(),
|
|
1106
|
+
id: options.account,
|
|
1107
|
+
period: options.period,
|
|
1108
|
+
}
|
|
1109
|
+
if (
|
|
1110
|
+
opening === undefined ||
|
|
1111
|
+
externalShareTransfer ||
|
|
1112
|
+
history.incompleteCostBasis ||
|
|
1113
|
+
opening.crossBoundaryRedemption ||
|
|
1114
|
+
opening.endShares !== current.shareBalance
|
|
1115
|
+
)
|
|
1116
|
+
return { ...base, status: 'incomplete_cost_basis' as const }
|
|
1117
|
+
if (history.pendingRedemption) return { ...base, status: 'pending_redemption' as const }
|
|
1118
|
+
const openingValue =
|
|
1119
|
+
opening.startShares === 0n
|
|
1120
|
+
? 0n
|
|
1121
|
+
: await client.earn.getRedeemQuote({
|
|
1122
|
+
blockNumber: BigInt(startBlockNumber),
|
|
1123
|
+
shareAmount: opening.startShares,
|
|
1124
|
+
vault: options.vault,
|
|
1125
|
+
})
|
|
1126
|
+
const windowEarnings = calculateWindowEarnings({
|
|
1127
|
+
deposited: history.deposited,
|
|
1128
|
+
endingValue: current.value,
|
|
1129
|
+
finalized: history.finalized,
|
|
1130
|
+
openingValue,
|
|
1131
|
+
redeemed: history.redeemed,
|
|
1132
|
+
withdrewExact: history.withdrewExact,
|
|
1133
|
+
})
|
|
1134
|
+
return { ...base, status: 'complete' as const, windowEarnings: windowEarnings.toString() }
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
declare namespace getWindowVaultEarnings {
|
|
1138
|
+
/** Inputs identifying one account, vault, and indexed window end. */
|
|
1139
|
+
type Options = {
|
|
1140
|
+
/** Account whose earnings are calculated. */
|
|
1141
|
+
account: z.output<typeof Schema.Address>
|
|
1142
|
+
/** Latest indexed block number. */
|
|
1143
|
+
blockNumber: number
|
|
1144
|
+
/** Tempo chain containing the vault. */
|
|
1145
|
+
chainId: z.output<typeof Schema.ChainId>
|
|
1146
|
+
/** Trailing earnings period. */
|
|
1147
|
+
period: '30d'
|
|
1148
|
+
/** Latest indexed block timestamp. */
|
|
1149
|
+
timestamp: string
|
|
1150
|
+
/** Earn vault contract address. */
|
|
1151
|
+
vault: z.output<typeof Schema.Address>
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
/** Calculates cash-flow-adjusted earnings between two position snapshots. */
|
|
1156
|
+
export function calculateWindowEarnings(options: calculateWindowEarnings.Options) {
|
|
1157
|
+
return (
|
|
1158
|
+
options.endingValue +
|
|
1159
|
+
options.redeemed +
|
|
1160
|
+
options.withdrewExact +
|
|
1161
|
+
options.finalized -
|
|
1162
|
+
options.deposited -
|
|
1163
|
+
options.openingValue
|
|
1164
|
+
)
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
export declare namespace calculateWindowEarnings {
|
|
1168
|
+
/** Asset-denominated values spanning one earnings window. */
|
|
1169
|
+
type Options = {
|
|
1170
|
+
/** Assets deposited during the window. */
|
|
1171
|
+
deposited: bigint
|
|
1172
|
+
/** Asset value of shares held at the ending boundary. */
|
|
1173
|
+
endingValue: bigint
|
|
1174
|
+
/** Assets received from async redemptions finalized during the window. */
|
|
1175
|
+
finalized: bigint
|
|
1176
|
+
/** Asset value of shares held at the opening boundary. */
|
|
1177
|
+
openingValue: bigint
|
|
1178
|
+
/** Assets received from redemptions during the window. */
|
|
1179
|
+
redeemed: bigint
|
|
1180
|
+
/** Assets received from exact withdrawals during the window. */
|
|
1181
|
+
withdrewExact: bigint
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1023
1185
|
export declare namespace getVaultEarnings {
|
|
1024
1186
|
/** Inputs identifying the account and vault to calculate. */
|
|
1025
1187
|
type Options = {
|
|
@@ -1031,16 +1193,45 @@ export declare namespace getVaultEarnings {
|
|
|
1031
1193
|
}
|
|
1032
1194
|
|
|
1033
1195
|
/** Reads the latest block whose indexed logs back the earnings calculation. */
|
|
1034
|
-
async function
|
|
1196
|
+
async function getLatestIndexedBlock(tidx: Tidx.Client) {
|
|
1035
1197
|
const result = await tidx.fetch({
|
|
1036
1198
|
engine: 'clickhouse',
|
|
1037
|
-
query: 'SELECT num FROM blocks ORDER BY num DESC LIMIT 1' as string,
|
|
1199
|
+
query: 'SELECT num, timestamp FROM blocks ORDER BY num DESC LIMIT 1' as string,
|
|
1200
|
+
})
|
|
1201
|
+
const number = Value.toNumber(result.rows[0]?.['num'])
|
|
1202
|
+
const timestamp = Value.toIsoDateTime(result.rows[0]?.['timestamp'])
|
|
1203
|
+
if (number === undefined || timestamp === undefined)
|
|
1204
|
+
throw new Error('TIDX returned no indexed block.')
|
|
1205
|
+
return { number, timestamp }
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
/** Resolves the last indexed block at or before a trailing-day boundary. */
|
|
1209
|
+
async function getWindowStartBlockNumber(
|
|
1210
|
+
tidx: Tidx.Client,
|
|
1211
|
+
options: getWindowStartBlockNumber.Options,
|
|
1212
|
+
) {
|
|
1213
|
+
const cutoff = new Date(Date.parse(options.timestamp) - Ttl.days(options.days)).toISOString()
|
|
1214
|
+
const result = await tidx.fetch({
|
|
1215
|
+
query:
|
|
1216
|
+
`SELECT num FROM blocks WHERE timestamp <= '${cutoff}' ORDER BY num DESC LIMIT 1` as string,
|
|
1038
1217
|
})
|
|
1039
|
-
const
|
|
1040
|
-
if (
|
|
1218
|
+
const row = result.rows[0]
|
|
1219
|
+
if (!row) return beforeFirstBlockNumber
|
|
1220
|
+
const blockNumber = Value.toNumber(row['num'])
|
|
1221
|
+
if (blockNumber === undefined) throw new Error('TIDX returned no Earn earnings boundary.')
|
|
1041
1222
|
return blockNumber
|
|
1042
1223
|
}
|
|
1043
1224
|
|
|
1225
|
+
declare namespace getWindowStartBlockNumber {
|
|
1226
|
+
/** Inputs defining a trailing boundary from an indexed timestamp. */
|
|
1227
|
+
type Options = {
|
|
1228
|
+
/** Number of trailing days. */
|
|
1229
|
+
days: number
|
|
1230
|
+
/** Timestamp anchoring the end of the window. */
|
|
1231
|
+
timestamp: string
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1044
1235
|
/** Reads the indexed cash flows and exceptional states behind one earnings calculation. */
|
|
1045
1236
|
async function getVaultEarningsHistory(
|
|
1046
1237
|
tidx: Tidx.Client,
|
|
@@ -1055,6 +1246,7 @@ async function getVaultEarningsHistory(
|
|
|
1055
1246
|
FROM Deposited
|
|
1056
1247
|
WHERE address = '${options.vault}'
|
|
1057
1248
|
AND receiver = '${options.account}'
|
|
1249
|
+
AND block_num > ${options.startBlockNumber}
|
|
1058
1250
|
AND block_num <= ${options.blockNumber}
|
|
1059
1251
|
) AS deposited_assets,
|
|
1060
1252
|
(
|
|
@@ -1065,6 +1257,7 @@ async function getVaultEarningsHistory(
|
|
|
1065
1257
|
AND requested."requestId" = finalized."requestId"
|
|
1066
1258
|
WHERE finalized.address = '${options.vault}'
|
|
1067
1259
|
AND requested.requester = '${options.account}'
|
|
1260
|
+
AND finalized.block_num > ${options.startBlockNumber}
|
|
1068
1261
|
AND finalized.block_num <= ${options.blockNumber}
|
|
1069
1262
|
AND requested.block_num <= ${options.blockNumber}
|
|
1070
1263
|
) AS finalized_assets,
|
|
@@ -1088,6 +1281,7 @@ async function getVaultEarningsHistory(
|
|
|
1088
1281
|
FROM Redeemed
|
|
1089
1282
|
WHERE address = '${options.vault}'
|
|
1090
1283
|
AND caller = '${options.account}'
|
|
1284
|
+
AND block_num > ${options.startBlockNumber}
|
|
1091
1285
|
AND block_num <= ${options.blockNumber}
|
|
1092
1286
|
) AS redeemed_assets,
|
|
1093
1287
|
(
|
|
@@ -1097,6 +1291,7 @@ async function getVaultEarningsHistory(
|
|
|
1097
1291
|
ON requested.address = cancelled.address
|
|
1098
1292
|
AND requested."requestId" = cancelled."requestId"
|
|
1099
1293
|
WHERE cancelled.address = '${options.vault}'
|
|
1294
|
+
AND cancelled.block_num > ${options.startBlockNumber}
|
|
1100
1295
|
AND cancelled.block_num <= ${options.blockNumber}
|
|
1101
1296
|
AND requested.block_num <= ${options.blockNumber}
|
|
1102
1297
|
AND requested.requester != cancelled.receiver
|
|
@@ -1110,6 +1305,7 @@ async function getVaultEarningsHistory(
|
|
|
1110
1305
|
FROM VenueSharesDeposited
|
|
1111
1306
|
WHERE address = '${options.vault}'
|
|
1112
1307
|
AND receiver = '${options.account}'
|
|
1308
|
+
AND block_num > ${options.startBlockNumber}
|
|
1113
1309
|
AND block_num <= ${options.blockNumber}
|
|
1114
1310
|
) AS venue_deposits,
|
|
1115
1311
|
(
|
|
@@ -1117,6 +1313,7 @@ async function getVaultEarningsHistory(
|
|
|
1117
1313
|
FROM WithdrewExact
|
|
1118
1314
|
WHERE address = '${options.vault}'
|
|
1119
1315
|
AND caller = '${options.account}'
|
|
1316
|
+
AND block_num > ${options.startBlockNumber}
|
|
1120
1317
|
AND block_num <= ${options.blockNumber}
|
|
1121
1318
|
) AS withdrew_exact
|
|
1122
1319
|
` as string,
|
|
@@ -1162,6 +1359,112 @@ declare namespace getVaultEarningsHistory {
|
|
|
1162
1359
|
type Options = {
|
|
1163
1360
|
account: z.output<typeof Schema.Address>
|
|
1164
1361
|
blockNumber: number
|
|
1362
|
+
startBlockNumber: number
|
|
1363
|
+
vault: z.output<typeof Schema.Address>
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
/** Reads share balances and cross-boundary redemptions for a trailing window. */
|
|
1368
|
+
async function getWindowShareState(tidx: Tidx.Client, options: getWindowShareState.Options) {
|
|
1369
|
+
const result = await tidx.fetch({
|
|
1370
|
+
engine: 'clickhouse',
|
|
1371
|
+
query: `
|
|
1372
|
+
SELECT
|
|
1373
|
+
(
|
|
1374
|
+
SELECT toString(sum(toUInt256(amount)))
|
|
1375
|
+
FROM token_transfers
|
|
1376
|
+
WHERE token = '${options.shareToken.toLowerCase()}'
|
|
1377
|
+
AND "to" = '${options.account}'
|
|
1378
|
+
AND block_num <= ${options.startBlockNumber}
|
|
1379
|
+
) AS received_start,
|
|
1380
|
+
(
|
|
1381
|
+
SELECT toString(sum(toUInt256(amount)))
|
|
1382
|
+
FROM token_transfers
|
|
1383
|
+
WHERE token = '${options.shareToken.toLowerCase()}'
|
|
1384
|
+
AND "from" = '${options.account}'
|
|
1385
|
+
AND block_num <= ${options.startBlockNumber}
|
|
1386
|
+
) AS sent_start,
|
|
1387
|
+
(
|
|
1388
|
+
SELECT toString(sum(toUInt256(amount)))
|
|
1389
|
+
FROM token_transfers
|
|
1390
|
+
WHERE token = '${options.shareToken.toLowerCase()}'
|
|
1391
|
+
AND "to" = '${options.account}'
|
|
1392
|
+
AND block_num <= ${options.blockNumber}
|
|
1393
|
+
) AS received_end,
|
|
1394
|
+
(
|
|
1395
|
+
SELECT toString(sum(toUInt256(amount)))
|
|
1396
|
+
FROM token_transfers
|
|
1397
|
+
WHERE token = '${options.shareToken.toLowerCase()}'
|
|
1398
|
+
AND "from" = '${options.account}'
|
|
1399
|
+
AND block_num <= ${options.blockNumber}
|
|
1400
|
+
) AS sent_end,
|
|
1401
|
+
(
|
|
1402
|
+
SELECT count()
|
|
1403
|
+
FROM (
|
|
1404
|
+
SELECT finalized."requestId"
|
|
1405
|
+
FROM RedeemFinalized AS finalized
|
|
1406
|
+
INNER JOIN RedeemRequested AS requested
|
|
1407
|
+
ON requested.address = finalized.address
|
|
1408
|
+
AND requested."requestId" = finalized."requestId"
|
|
1409
|
+
WHERE finalized.address = '${options.vault}'
|
|
1410
|
+
AND requested.requester = '${options.account}'
|
|
1411
|
+
AND requested.block_num <= ${options.startBlockNumber}
|
|
1412
|
+
AND finalized.block_num > ${options.startBlockNumber}
|
|
1413
|
+
AND finalized.block_num <= ${options.blockNumber}
|
|
1414
|
+
UNION ALL
|
|
1415
|
+
SELECT cancelled."requestId"
|
|
1416
|
+
FROM RedeemCancelled AS cancelled
|
|
1417
|
+
INNER JOIN RedeemRequested AS requested
|
|
1418
|
+
ON requested.address = cancelled.address
|
|
1419
|
+
AND requested."requestId" = cancelled."requestId"
|
|
1420
|
+
WHERE cancelled.address = '${options.vault}'
|
|
1421
|
+
AND requested.requester = '${options.account}'
|
|
1422
|
+
AND requested.block_num <= ${options.startBlockNumber}
|
|
1423
|
+
AND cancelled.block_num > ${options.startBlockNumber}
|
|
1424
|
+
AND cancelled.block_num <= ${options.blockNumber}
|
|
1425
|
+
) AS cross_boundary
|
|
1426
|
+
) AS cross_boundary_redemptions
|
|
1427
|
+
` as string,
|
|
1428
|
+
signatures: [redeemCancelledSignature, redeemFinalizedSignature, redeemRequestedSignature],
|
|
1429
|
+
})
|
|
1430
|
+
const row = result.rows[0]
|
|
1431
|
+
const crossBoundaryRedemptions = Value.toNumber(row?.['cross_boundary_redemptions'])
|
|
1432
|
+
const receivedEnd = Value.toIntegerString(row?.['received_end'])
|
|
1433
|
+
const receivedStart = Value.toIntegerString(row?.['received_start'])
|
|
1434
|
+
const sentEnd = Value.toIntegerString(row?.['sent_end'])
|
|
1435
|
+
const sentStart = Value.toIntegerString(row?.['sent_start'])
|
|
1436
|
+
if (
|
|
1437
|
+
crossBoundaryRedemptions === undefined ||
|
|
1438
|
+
receivedEnd === undefined ||
|
|
1439
|
+
receivedStart === undefined ||
|
|
1440
|
+
sentEnd === undefined ||
|
|
1441
|
+
sentStart === undefined
|
|
1442
|
+
)
|
|
1443
|
+
return undefined
|
|
1444
|
+
const receivedEndValue = BigInt(receivedEnd)
|
|
1445
|
+
const receivedStartValue = BigInt(receivedStart)
|
|
1446
|
+
const sentEndValue = BigInt(sentEnd)
|
|
1447
|
+
const sentStartValue = BigInt(sentStart)
|
|
1448
|
+
if (sentEndValue > receivedEndValue || sentStartValue > receivedStartValue) return undefined
|
|
1449
|
+
return {
|
|
1450
|
+
crossBoundaryRedemption: crossBoundaryRedemptions > 0,
|
|
1451
|
+
endShares: receivedEndValue - sentEndValue,
|
|
1452
|
+
startShares: receivedStartValue - sentStartValue,
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
declare namespace getWindowShareState {
|
|
1457
|
+
/** Inputs identifying one account's share history window. */
|
|
1458
|
+
type Options = {
|
|
1459
|
+
/** Account whose share history is read. */
|
|
1460
|
+
account: z.output<typeof Schema.Address>
|
|
1461
|
+
/** Ending indexed block number. */
|
|
1462
|
+
blockNumber: number
|
|
1463
|
+
/** Earn share token contract address. */
|
|
1464
|
+
shareToken: z.output<typeof Schema.Address>
|
|
1465
|
+
/** Opening indexed block number. */
|
|
1466
|
+
startBlockNumber: number
|
|
1467
|
+
/** Earn vault contract address. */
|
|
1165
1468
|
vault: z.output<typeof Schema.Address>
|
|
1166
1469
|
}
|
|
1167
1470
|
}
|
|
@@ -1180,10 +1483,15 @@ async function hasExternalShareTransfer(
|
|
|
1180
1483
|
SELECT count()
|
|
1181
1484
|
FROM token_transfers
|
|
1182
1485
|
WHERE token = '${options.shareToken.toLowerCase()}'
|
|
1486
|
+
AND block_num > ${options.startBlockNumber}
|
|
1183
1487
|
AND block_num <= ${options.blockNumber}
|
|
1184
1488
|
AND (
|
|
1185
1489
|
("from" = '${options.account}' AND "to" != '${options.vault}')
|
|
1186
|
-
OR (
|
|
1490
|
+
OR (
|
|
1491
|
+
"to" = '${options.account}'
|
|
1492
|
+
AND "from" != '${zeroAddress}'
|
|
1493
|
+
AND "from" != '${options.vault}'
|
|
1494
|
+
)
|
|
1187
1495
|
)
|
|
1188
1496
|
) + (
|
|
1189
1497
|
SELECT count()
|
|
@@ -1193,6 +1501,7 @@ async function hasExternalShareTransfer(
|
|
|
1193
1501
|
WHERE token = '${options.shareToken.toLowerCase()}'
|
|
1194
1502
|
AND "from" = '${options.account}'
|
|
1195
1503
|
AND "to" = '${options.vault}'
|
|
1504
|
+
AND block_num > ${options.startBlockNumber}
|
|
1196
1505
|
AND block_num <= ${options.blockNumber}
|
|
1197
1506
|
GROUP BY tx_hash, amount
|
|
1198
1507
|
) AS candidate
|
|
@@ -1203,27 +1512,58 @@ async function hasExternalShareTransfer(
|
|
|
1203
1512
|
FROM Redeemed
|
|
1204
1513
|
WHERE address = '${options.vault}'
|
|
1205
1514
|
AND caller = '${options.account}'
|
|
1515
|
+
AND block_num > ${options.startBlockNumber}
|
|
1206
1516
|
AND block_num <= ${options.blockNumber}
|
|
1207
1517
|
UNION ALL
|
|
1208
1518
|
SELECT tx_hash, toUInt256(earnShares) AS amount
|
|
1209
1519
|
FROM RedeemRequested
|
|
1210
1520
|
WHERE address = '${options.vault}'
|
|
1211
1521
|
AND requester = '${options.account}'
|
|
1522
|
+
AND block_num > ${options.startBlockNumber}
|
|
1212
1523
|
AND block_num <= ${options.blockNumber}
|
|
1213
1524
|
UNION ALL
|
|
1214
1525
|
SELECT tx_hash, toUInt256(earnSharesBurned) AS amount
|
|
1215
1526
|
FROM WithdrewExact
|
|
1216
1527
|
WHERE address = '${options.vault}'
|
|
1217
1528
|
AND caller = '${options.account}'
|
|
1529
|
+
AND block_num > ${options.startBlockNumber}
|
|
1218
1530
|
AND block_num <= ${options.blockNumber}
|
|
1219
1531
|
) AS protocol_exit
|
|
1220
1532
|
GROUP BY tx_hash, amount
|
|
1221
1533
|
) AS matched
|
|
1222
1534
|
ON matched.tx_hash = candidate.tx_hash AND matched.amount = candidate.amount
|
|
1223
1535
|
WHERE candidate.transfer_count > coalesce(matched.exit_count, 0)
|
|
1536
|
+
) + (
|
|
1537
|
+
SELECT count()
|
|
1538
|
+
FROM (
|
|
1539
|
+
SELECT tx_hash, toUInt256(amount) AS amount, count() AS transfer_count
|
|
1540
|
+
FROM token_transfers
|
|
1541
|
+
WHERE token = '${options.shareToken.toLowerCase()}'
|
|
1542
|
+
AND "from" = '${options.vault}'
|
|
1543
|
+
AND "to" = '${options.account}'
|
|
1544
|
+
AND block_num > ${options.startBlockNumber}
|
|
1545
|
+
AND block_num <= ${options.blockNumber}
|
|
1546
|
+
GROUP BY tx_hash, amount
|
|
1547
|
+
) AS candidate
|
|
1548
|
+
LEFT JOIN (
|
|
1549
|
+
SELECT tx_hash, toUInt256(earnShares) AS amount, count() AS cancel_count
|
|
1550
|
+
FROM RedeemCancelled
|
|
1551
|
+
WHERE address = '${options.vault}'
|
|
1552
|
+
AND receiver = '${options.account}'
|
|
1553
|
+
AND block_num > ${options.startBlockNumber}
|
|
1554
|
+
AND block_num <= ${options.blockNumber}
|
|
1555
|
+
GROUP BY tx_hash, amount
|
|
1556
|
+
) AS matched
|
|
1557
|
+
ON matched.tx_hash = candidate.tx_hash AND matched.amount = candidate.amount
|
|
1558
|
+
WHERE candidate.transfer_count > coalesce(matched.cancel_count, 0)
|
|
1224
1559
|
) AS count
|
|
1225
1560
|
` as string,
|
|
1226
|
-
signatures: [
|
|
1561
|
+
signatures: [
|
|
1562
|
+
redeemCancelledSignature,
|
|
1563
|
+
redeemedSignature,
|
|
1564
|
+
redeemRequestedSignature,
|
|
1565
|
+
withdrewExactSignature,
|
|
1566
|
+
],
|
|
1227
1567
|
})
|
|
1228
1568
|
const count = Value.toNumber(result.rows[0]?.['count'])
|
|
1229
1569
|
if (count === undefined) throw new Error('TIDX returned an invalid Earn-share transfer count.')
|
|
@@ -1235,6 +1575,7 @@ declare namespace hasExternalShareTransfer {
|
|
|
1235
1575
|
account: z.output<typeof Schema.Address>
|
|
1236
1576
|
blockNumber: number
|
|
1237
1577
|
shareToken: z.output<typeof Schema.Address>
|
|
1578
|
+
startBlockNumber: number
|
|
1238
1579
|
vault: z.output<typeof Schema.Address>
|
|
1239
1580
|
}
|
|
1240
1581
|
}
|
package/src/apps/funding/App.ts
CHANGED
|
@@ -42,22 +42,37 @@ export declare namespace funding {
|
|
|
42
42
|
|
|
43
43
|
const openapi = {
|
|
44
44
|
tags: [
|
|
45
|
-
{
|
|
45
|
+
{
|
|
46
|
+
name: 'Chains',
|
|
47
|
+
description: 'Source chains and stablecoins supported for funding.',
|
|
48
|
+
'x-pagePath': 'funding/chains',
|
|
49
|
+
},
|
|
46
50
|
{
|
|
47
51
|
name: 'Deposit Addresses',
|
|
48
52
|
description: 'Reusable funding addresses and deposits detected at those addresses.',
|
|
53
|
+
'x-pagePath': 'funding/deposit-addresses',
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: 'Providers',
|
|
57
|
+
description: 'Providers available for inbound funding.',
|
|
58
|
+
'x-pagePath': 'funding/providers',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'Quotes',
|
|
62
|
+
description: 'Live quotes for funding Tempo from other chains.',
|
|
63
|
+
'x-pagePath': 'funding/quotes',
|
|
49
64
|
},
|
|
50
|
-
{ name: 'Providers', description: 'Providers available for inbound funding.' },
|
|
51
|
-
{ name: 'Quotes', description: 'Live quotes for funding Tempo from other chains.' },
|
|
52
65
|
{
|
|
53
|
-
name: 'Transfers',
|
|
66
|
+
name: 'Funding Transfers',
|
|
54
67
|
description: 'Inbound funding transfers.',
|
|
68
|
+
'x-displayName': 'Transfers',
|
|
69
|
+
'x-pagePath': 'funding/transfers',
|
|
55
70
|
},
|
|
56
71
|
],
|
|
57
72
|
'x-tagGroups': [
|
|
58
73
|
{
|
|
59
74
|
name: 'Funding & Bridge API',
|
|
60
|
-
tags: ['Chains', 'Deposit Addresses', 'Providers', 'Quotes', 'Transfers'],
|
|
75
|
+
tags: ['Chains', 'Deposit Addresses', 'Providers', 'Quotes', 'Funding Transfers'],
|
|
61
76
|
},
|
|
62
77
|
],
|
|
63
78
|
} satisfies App.create.Metadata
|