@gearbox-protocol/sdk 15.1.0-next.10 → 15.1.0-next.12
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/cjs/dev/mode-parity/compareOpportunities.js +105 -0
- package/dist/cjs/dev/mode-parity/comparePositions.js +160 -0
- package/dist/cjs/dev/mode-parity/compareRules.js +93 -0
- package/dist/cjs/dev/mode-parity/fieldDiff.js +288 -0
- package/dist/cjs/dev/mode-parity/scriptUtils.js +131 -0
- package/dist/cjs/model/compare.schema.js +33 -0
- package/dist/cjs/model/curators.schema.js +2 -1
- package/dist/cjs/model/index.js +5 -0
- package/dist/cjs/model/opportunities.schema.js +13 -12
- package/dist/cjs/model/positions.schema.js +15 -14
- package/dist/cjs/model/primitives.schema.js +2 -1
- package/dist/cjs/sdk/market/math.js +8 -1
- package/dist/cjs/sdk/pools/PoolService.js +1 -1
- package/dist/cjs/sdk/positions/PositionsService.js +6 -1
- package/dist/esm/common-utils/index.js +3 -3
- package/dist/esm/common-utils/utils/index.js +1 -1
- package/dist/esm/dev/mode-parity/compareOpportunities.js +103 -0
- package/dist/esm/dev/mode-parity/comparePositions.js +158 -0
- package/dist/esm/dev/mode-parity/compareRules.js +91 -0
- package/dist/esm/dev/mode-parity/fieldDiff.js +270 -0
- package/dist/esm/dev/mode-parity/scriptUtils.js +121 -0
- package/dist/esm/model/compare.schema.js +29 -0
- package/dist/esm/model/curators.schema.js +2 -1
- package/dist/esm/model/index.js +2 -1
- package/dist/esm/model/opportunities.schema.js +13 -12
- package/dist/esm/model/positions.schema.js +15 -14
- package/dist/esm/model/primitives.schema.js +2 -1
- package/dist/esm/plugins/apy/ApyPlugin.js +2 -2
- package/dist/esm/sdk/market/math.js +8 -1
- package/dist/esm/sdk/pools/PoolService.js +1 -1
- package/dist/esm/sdk/positions/PositionsService.js +6 -1
- package/dist/types/dev/{compareOpportunities.d.ts → mode-parity/compareOpportunities.d.ts} +18 -66
- package/dist/types/dev/mode-parity/comparePositions.d.ts +149 -0
- package/dist/types/dev/mode-parity/compareRules.d.ts +33 -0
- package/dist/types/dev/mode-parity/fieldDiff.d.ts +209 -0
- package/dist/types/dev/mode-parity/scriptUtils.d.ts +47 -0
- package/dist/types/model/compare.schema.d.ts +47 -0
- package/dist/types/model/index.d.ts +2 -1
- package/dist/types/sdk/market/math.d.ts +2 -0
- package/package.json +1 -1
- package/dist/cjs/dev/compareOpportunities.js +0 -218
- package/dist/esm/dev/compareOpportunities.js +0 -216
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
import { opportunityId } from "../model/opportunities.js";
|
|
2
|
-
import "../model/index.js";
|
|
3
|
-
//#region src/dev/compareOpportunities.ts
|
|
4
|
-
/**
|
|
5
|
-
* Matches two opportunity listings by {@link opportunityId} and reports every
|
|
6
|
-
* field the two sources disagree on.
|
|
7
|
-
*
|
|
8
|
-
* Nothing is filtered out: a diff that is expected — a field only the backend
|
|
9
|
-
* can fill, a formula the two sides define differently, a USD value smoothed on
|
|
10
|
-
* one side — is reported like any other, tagged by {@link DiffKind} so that a
|
|
11
|
-
* reader can bucket it afterwards.
|
|
12
|
-
**/
|
|
13
|
-
function compareOpportunities(input) {
|
|
14
|
-
const onchainRows = indexById(input.onchain.data);
|
|
15
|
-
const offchainRows = indexById(input.offchain.data);
|
|
16
|
-
const onlyOnchain = [];
|
|
17
|
-
const onlyOffchain = [];
|
|
18
|
-
const matched = [];
|
|
19
|
-
for (const [id, row] of onchainRows) {
|
|
20
|
-
const counterpart = offchainRows.get(id);
|
|
21
|
-
if (!counterpart) {
|
|
22
|
-
onlyOnchain.push(toRef(row));
|
|
23
|
-
continue;
|
|
24
|
-
}
|
|
25
|
-
const diffs = diffOpportunity(row, counterpart);
|
|
26
|
-
matched.push({
|
|
27
|
-
id,
|
|
28
|
-
kind: row.kind,
|
|
29
|
-
chainId: row.chainId,
|
|
30
|
-
onchainName: row.name,
|
|
31
|
-
offchainName: counterpart.name,
|
|
32
|
-
identical: diffs.length === 0,
|
|
33
|
-
diffs
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
for (const [id, row] of offchainRows) if (!onchainRows.has(id)) onlyOffchain.push(toRef(row));
|
|
37
|
-
byId(onlyOnchain);
|
|
38
|
-
byId(onlyOffchain);
|
|
39
|
-
matched.sort((a, b) => a.id.localeCompare(b.id));
|
|
40
|
-
return {
|
|
41
|
-
generatedAt: input.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
42
|
-
backendUrl: input.backendUrl,
|
|
43
|
-
networks: [...input.networks],
|
|
44
|
-
onchainChains: input.onchain.meta.chains,
|
|
45
|
-
offchainChains: input.offchain.meta.chains,
|
|
46
|
-
summary: summarize(input.onchain.data, input.offchain.data, onlyOnchain, onlyOffchain, matched),
|
|
47
|
-
onlyOnchain,
|
|
48
|
-
onlyOffchain,
|
|
49
|
-
matched
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
function indexById(rows) {
|
|
53
|
-
return new Map(rows.map((row) => [opportunityId(row), row]));
|
|
54
|
-
}
|
|
55
|
-
function byId(refs) {
|
|
56
|
-
refs.sort((a, b) => a.id.localeCompare(b.id));
|
|
57
|
-
}
|
|
58
|
-
function toRef(row) {
|
|
59
|
-
const base = {
|
|
60
|
-
id: opportunityId(row),
|
|
61
|
-
kind: row.kind,
|
|
62
|
-
chainId: row.chainId,
|
|
63
|
-
name: row.name
|
|
64
|
-
};
|
|
65
|
-
return row.kind === "pool" ? {
|
|
66
|
-
...base,
|
|
67
|
-
pool: row.pool
|
|
68
|
-
} : {
|
|
69
|
-
...base,
|
|
70
|
-
creditManager: row.creditManager,
|
|
71
|
-
targetCollateral: row.targetCollateral.address
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Every field two versions of one opportunity disagree on.
|
|
76
|
-
**/
|
|
77
|
-
function diffOpportunity(onchain, offchain) {
|
|
78
|
-
const diffs = [];
|
|
79
|
-
diffValue("", onchain, offchain, diffs);
|
|
80
|
-
return diffs;
|
|
81
|
-
}
|
|
82
|
-
function diffValue(path, onchain, offchain, out) {
|
|
83
|
-
if (isAbsent(onchain) && isAbsent(offchain)) return;
|
|
84
|
-
if (isAbsent(onchain) || isAbsent(offchain)) {
|
|
85
|
-
out.push({
|
|
86
|
-
path,
|
|
87
|
-
onchain,
|
|
88
|
-
offchain,
|
|
89
|
-
kind: "presence"
|
|
90
|
-
});
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
if (Array.isArray(onchain) && Array.isArray(offchain)) {
|
|
94
|
-
diffArray(path, onchain, offchain, out);
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
if (isRecord(onchain) && isRecord(offchain)) {
|
|
98
|
-
for (const key of union(Object.keys(onchain), Object.keys(offchain))) diffValue(join(path, key), onchain[key], offchain[key], out);
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
if (!sameScalar(onchain, offchain)) out.push({
|
|
102
|
-
path,
|
|
103
|
-
onchain,
|
|
104
|
-
offchain,
|
|
105
|
-
kind: scalarKind(path, onchain)
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Arrays whose elements identify themselves — collateral tokens, points
|
|
110
|
-
* programs — are matched by that identity, so a token present on one side only
|
|
111
|
-
* is reported as such rather than shifting every later element into a diff.
|
|
112
|
-
**/
|
|
113
|
-
function diffArray(path, onchain, offchain, out) {
|
|
114
|
-
const onchainKeyed = keyElements(onchain);
|
|
115
|
-
const offchainKeyed = keyElements(offchain);
|
|
116
|
-
if (!onchainKeyed || !offchainKeyed) {
|
|
117
|
-
if (onchain.length !== offchain.length) {
|
|
118
|
-
out.push({
|
|
119
|
-
path,
|
|
120
|
-
onchain,
|
|
121
|
-
offchain,
|
|
122
|
-
kind: "other"
|
|
123
|
-
});
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
onchain.forEach((element, index) => {
|
|
127
|
-
diffValue(`${path}[${index}]`, element, offchain[index], out);
|
|
128
|
-
});
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
for (const key of union([...onchainKeyed.keys()], [...offchainKeyed.keys()])) diffValue(`${path}[${key}]`, onchainKeyed.get(key), offchainKeyed.get(key), out);
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* The array indexed by each element's own identity, or `undefined` when its
|
|
135
|
-
* elements have none and order is all there is to go by.
|
|
136
|
-
**/
|
|
137
|
-
function keyElements(values) {
|
|
138
|
-
const keyed = /* @__PURE__ */ new Map();
|
|
139
|
-
for (const value of values) {
|
|
140
|
-
if (!isRecord(value)) return;
|
|
141
|
-
const identity = value.address ?? value.id ?? value.token;
|
|
142
|
-
if (typeof identity !== "string") return;
|
|
143
|
-
keyed.set(identity.toLowerCase(), value);
|
|
144
|
-
}
|
|
145
|
-
return keyed.size === values.length ? keyed : void 0;
|
|
146
|
-
}
|
|
147
|
-
const ADDRESS = /^0x[0-9a-f]{40}$/i;
|
|
148
|
-
/**
|
|
149
|
-
* Only addresses are compared case-insensitively: the backend lowercases them
|
|
150
|
-
* while the chain hands out checksummed ones, which is not a disagreement. A
|
|
151
|
-
* symbol or a name spelled differently is.
|
|
152
|
-
**/
|
|
153
|
-
function sameScalar(onchain, offchain) {
|
|
154
|
-
if (typeof onchain === "string" && typeof offchain === "string" && ADDRESS.test(onchain) && ADDRESS.test(offchain)) return onchain.toLowerCase() === offchain.toLowerCase();
|
|
155
|
-
return onchain === offchain;
|
|
156
|
-
}
|
|
157
|
-
function scalarKind(path, onchain) {
|
|
158
|
-
if (path.endsWith("valueUsd")) return "usd";
|
|
159
|
-
return typeof onchain === "number" || typeof onchain === "bigint" ? "numeric" : "other";
|
|
160
|
-
}
|
|
161
|
-
function summarize(onchain, offchain, onlyOnchain, onlyOffchain, matched) {
|
|
162
|
-
const byChain = union(onchain.map((row) => String(row.chainId)), offchain.map((row) => String(row.chainId))).map((chainId) => ({
|
|
163
|
-
chainId: Number(chainId),
|
|
164
|
-
...count(onchain.filter((row) => String(row.chainId) === chainId), offchain.filter((row) => String(row.chainId) === chainId), onlyOnchain.filter((ref) => String(ref.chainId) === chainId), onlyOffchain.filter((ref) => String(ref.chainId) === chainId), matched.filter((match) => String(match.chainId) === chainId))
|
|
165
|
-
})).sort((a, b) => a.chainId - b.chainId);
|
|
166
|
-
return {
|
|
167
|
-
...count(onchain, offchain, onlyOnchain, onlyOffchain, matched),
|
|
168
|
-
byChain,
|
|
169
|
-
diffsByPath: countPaths(matched)
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
function count(onchain, offchain, onlyOnchain, onlyOffchain, matched) {
|
|
173
|
-
const identical = matched.filter((match) => match.identical).length;
|
|
174
|
-
return {
|
|
175
|
-
onchainRows: onchain.length,
|
|
176
|
-
offchainRows: offchain.length,
|
|
177
|
-
matched: matched.length,
|
|
178
|
-
identical,
|
|
179
|
-
differing: matched.length - identical,
|
|
180
|
-
onlyOnchain: onlyOnchain.length,
|
|
181
|
-
onlyOffchain: onlyOffchain.length
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* How often each field differed, with array keys collapsed so that the same
|
|
186
|
-
* field of a hundred collateral tokens counts as one path.
|
|
187
|
-
**/
|
|
188
|
-
function countPaths(matched) {
|
|
189
|
-
const counts = /* @__PURE__ */ new Map();
|
|
190
|
-
for (const match of matched) for (const diff of match.diffs) {
|
|
191
|
-
const path = diff.path.replace(/\[[^\]]*\]/g, "[]");
|
|
192
|
-
const entry = counts.get(path) ?? {
|
|
193
|
-
path,
|
|
194
|
-
kinds: [],
|
|
195
|
-
count: 0
|
|
196
|
-
};
|
|
197
|
-
entry.count += 1;
|
|
198
|
-
if (!entry.kinds.includes(diff.kind)) entry.kinds.push(diff.kind);
|
|
199
|
-
counts.set(path, entry);
|
|
200
|
-
}
|
|
201
|
-
return [...counts.values()].sort((a, b) => b.count - a.count || a.path.localeCompare(b.path));
|
|
202
|
-
}
|
|
203
|
-
function isAbsent(value) {
|
|
204
|
-
return value === void 0 || value === null;
|
|
205
|
-
}
|
|
206
|
-
function isRecord(value) {
|
|
207
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
208
|
-
}
|
|
209
|
-
function union(left, right) {
|
|
210
|
-
return [.../* @__PURE__ */ new Set([...left, ...right])];
|
|
211
|
-
}
|
|
212
|
-
function join(path, key) {
|
|
213
|
-
return path ? `${path}.${key}` : key;
|
|
214
|
-
}
|
|
215
|
-
//#endregion
|
|
216
|
-
export { compareOpportunities, diffOpportunity };
|