@gearbox-protocol/sdk 17.10.1 → 17.11.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 (112) hide show
  1. package/dist/cjs/offchain/AbstractOffchainNamespace.js +31 -8
  2. package/dist/cjs/permissionless/api/GearboxPermissionless.js +79 -0
  3. package/dist/cjs/permissionless/api/chains/ChainsNamespace.js +180 -0
  4. package/dist/cjs/permissionless/api/chains/index.js +4 -0
  5. package/dist/cjs/permissionless/api/chains/schemas.js +34 -0
  6. package/dist/cjs/permissionless/api/chains/types.js +1 -0
  7. package/dist/cjs/permissionless/api/deploy/PermissionlessDeploy.js +152 -0
  8. package/dist/cjs/permissionless/api/deploy/effective-staleness.js +46 -0
  9. package/dist/cjs/permissionless/api/deploy/index.js +8 -0
  10. package/dist/cjs/permissionless/api/deploy/types.js +1 -0
  11. package/dist/cjs/permissionless/api/errors.js +82 -0
  12. package/dist/cjs/permissionless/api/index.js +28 -0
  13. package/dist/cjs/permissionless/api/oracles/PermissionlessOracles.js +84 -0
  14. package/dist/cjs/permissionless/api/oracles/index.js +6 -0
  15. package/dist/cjs/permissionless/api/oracles/schemas.js +64 -0
  16. package/dist/cjs/permissionless/api/oracles/types.js +1 -0
  17. package/dist/cjs/permissionless/api/schemas.js +28 -0
  18. package/dist/cjs/permissionless/api/transactions/InstanceOwnerTransactions.js +230 -0
  19. package/dist/cjs/permissionless/api/transactions/index.js +4 -0
  20. package/dist/cjs/permissionless/api/transactions/lp-price-feeds.js +86 -0
  21. package/dist/cjs/permissionless/api/transactions/types.js +1 -0
  22. package/dist/cjs/permissionless/api/types.js +1 -0
  23. package/dist/cjs/permissionless/bindings/cross-chain-multisig.js +1 -1
  24. package/dist/cjs/permissionless/bindings/index.js +3 -3
  25. package/dist/cjs/permissionless/bindings/instance-manager.js +3 -3
  26. package/dist/cjs/permissionless/index.js +31 -8
  27. package/dist/cjs/permissionless/utils/governance/timelock-txs.js +1 -1
  28. package/dist/cjs/permissionless/utils/index.js +4 -4
  29. package/dist/cjs/permissionless/utils/price-update/get-price-update-tx.js +1 -1
  30. package/dist/cjs/permissionless/utils/price-update/index.js +1 -1
  31. package/dist/esm/dev/AccountOpener.js +1 -1
  32. package/dist/esm/dev/withdrawalUtils.js +1 -1
  33. package/dist/esm/history/trace/extractTransfers.js +1 -1
  34. package/dist/esm/offchain/AbstractOffchainNamespace.js +31 -8
  35. package/dist/esm/onchain/accounts/CreditAccountsServiceV310.js +2 -2
  36. package/dist/esm/onchain/accounts/liquidations/LiquidationsService.js +1 -1
  37. package/dist/esm/onchain/accounts/withdrawal-compressor/RedemptionLoggerV310Contract.js +1 -1
  38. package/dist/esm/onchain/accounts/withdrawal-compressor/WithdrawalCompressorV310Contract.js +1 -1
  39. package/dist/esm/onchain/accounts/withdrawal-compressor/WithdrawalCompressorV311Contract.js +1 -1
  40. package/dist/esm/onchain/accounts/withdrawal-compressor/WithdrawalCompressorV313Contract.js +1 -1
  41. package/dist/esm/onchain/base/TokensMeta.js +3 -3
  42. package/dist/esm/onchain/core/createAddressProvider.js +1 -1
  43. package/dist/esm/onchain/market/adapters/contracts/AccountMigratorAdapterContract.js +1 -1
  44. package/dist/esm/onchain/market/adapters/contracts/ERC4626AdapterContract.js +1 -1
  45. package/dist/esm/onchain/market/credit/CreditFacadeV310BaseContract.js +1 -1
  46. package/dist/esm/onchain/market/pool/PoolV310Contract.js +1 -1
  47. package/dist/esm/onchain/market/rwa/createDegenNFT.js +1 -1
  48. package/dist/esm/onchain/market/zapper/IETHZapperContract.js +1 -1
  49. package/dist/esm/onchain/market/zapper/ZapperContract.js +1 -1
  50. package/dist/esm/onchain/preview/preview/previewPoolPositionOperation.js +2 -2
  51. package/dist/esm/onchain/utils/viem/simulateWithPriceUpdates.js +1 -1
  52. package/dist/esm/permissionless/api/GearboxPermissionless.js +78 -0
  53. package/dist/esm/permissionless/api/chains/ChainsNamespace.js +179 -0
  54. package/dist/esm/permissionless/api/chains/index.js +3 -0
  55. package/dist/esm/permissionless/api/chains/schemas.js +30 -0
  56. package/dist/esm/permissionless/api/chains/types.js +1 -0
  57. package/dist/esm/permissionless/api/deploy/PermissionlessDeploy.js +149 -0
  58. package/dist/esm/permissionless/api/deploy/effective-staleness.js +46 -0
  59. package/dist/esm/permissionless/api/deploy/index.js +4 -0
  60. package/dist/esm/permissionless/api/deploy/types.js +1 -0
  61. package/dist/esm/permissionless/api/errors.js +77 -0
  62. package/dist/esm/permissionless/api/index.js +13 -0
  63. package/dist/esm/permissionless/api/oracles/PermissionlessOracles.js +81 -0
  64. package/dist/esm/permissionless/api/oracles/index.js +3 -0
  65. package/dist/esm/permissionless/api/oracles/schemas.js +59 -0
  66. package/dist/esm/permissionless/api/oracles/types.js +1 -0
  67. package/dist/esm/permissionless/api/schemas.js +25 -0
  68. package/dist/esm/permissionless/api/transactions/InstanceOwnerTransactions.js +229 -0
  69. package/dist/esm/permissionless/api/transactions/index.js +3 -0
  70. package/dist/esm/permissionless/api/transactions/lp-price-feeds.js +84 -0
  71. package/dist/esm/permissionless/api/transactions/types.js +1 -0
  72. package/dist/esm/permissionless/api/types.js +1 -0
  73. package/dist/esm/permissionless/bindings/cross-chain-multisig.js +1 -1
  74. package/dist/esm/permissionless/bindings/index.js +3 -3
  75. package/dist/esm/permissionless/bindings/instance-manager.js +3 -3
  76. package/dist/esm/permissionless/index.js +17 -9
  77. package/dist/esm/permissionless/utils/governance/timelock-txs.js +1 -1
  78. package/dist/esm/permissionless/utils/index.js +4 -4
  79. package/dist/esm/permissionless/utils/price-update/get-price-update-tx.js +1 -1
  80. package/dist/esm/permissionless/utils/price-update/index.js +1 -1
  81. package/dist/types/offchain/AbstractOffchainNamespace.d.ts +12 -0
  82. package/dist/types/permissionless/api/GearboxPermissionless.d.ts +71 -0
  83. package/dist/types/permissionless/api/chains/ChainsNamespace.d.ts +99 -0
  84. package/dist/types/permissionless/api/chains/index.d.ts +3 -0
  85. package/dist/types/permissionless/api/chains/schemas.d.ts +49 -0
  86. package/dist/types/permissionless/api/chains/types.d.ts +58 -0
  87. package/dist/types/permissionless/api/deploy/PermissionlessDeploy.d.ts +69 -0
  88. package/dist/types/permissionless/api/deploy/effective-staleness.d.ts +19 -0
  89. package/dist/types/permissionless/api/deploy/index.d.ts +4 -0
  90. package/dist/types/permissionless/api/deploy/types.d.ts +87 -0
  91. package/dist/types/permissionless/api/errors.d.ts +63 -0
  92. package/dist/types/permissionless/api/index.d.ts +17 -0
  93. package/dist/types/permissionless/api/oracles/PermissionlessOracles.d.ts +64 -0
  94. package/dist/types/permissionless/api/oracles/index.d.ts +3 -0
  95. package/dist/types/permissionless/api/oracles/schemas.d.ts +103 -0
  96. package/dist/types/permissionless/api/oracles/types.d.ts +63 -0
  97. package/dist/types/permissionless/api/schemas.d.ts +22 -0
  98. package/dist/types/permissionless/api/transactions/InstanceOwnerTransactions.d.ts +60 -0
  99. package/dist/types/permissionless/api/transactions/index.d.ts +3 -0
  100. package/dist/types/permissionless/api/transactions/lp-price-feeds.d.ts +17 -0
  101. package/dist/types/permissionless/api/transactions/types.d.ts +36 -0
  102. package/dist/types/permissionless/api/types.d.ts +12 -0
  103. package/dist/types/permissionless/bindings/factory/credit-factory.d.ts +1 -1
  104. package/dist/types/permissionless/bindings/factory/loss-policy-factory.d.ts +1 -1
  105. package/dist/types/permissionless/bindings/factory/pool-factory.d.ts +1 -1
  106. package/dist/types/permissionless/bindings/factory/price-oracle-factory.d.ts +1 -1
  107. package/dist/types/permissionless/bindings/index.d.ts +1 -1
  108. package/dist/types/permissionless/core/index.d.ts +1 -1
  109. package/dist/types/permissionless/index.d.ts +23 -10
  110. package/dist/types/permissionless/utils/governance/index.d.ts +1 -1
  111. package/dist/types/permissionless/utils/index.d.ts +1 -1
  112. package/package.json +1 -1
@@ -0,0 +1,25 @@
1
+ import { isAddress, isHex } from "viem";
2
+ import { z } from "zod/v4";
3
+ //#region src/permissionless/api/schemas.ts
4
+ /**
5
+ * Runtime schemas shared by the {@link GearboxPermissionless} namespaces.
6
+ *
7
+ * Addresses are validated but never rewritten: the backend serves them in the
8
+ * case its database holds, and its payloads key records by address, so
9
+ * checksumming here would silently break a lookup by the key it answered with.
10
+ * A caller that needs one form converts with viem's `getAddress`.
11
+ **/
12
+ /** An address, in whatever case the backend serves it. */
13
+ const addressSchema = z.custom((value) => typeof value === "string" && isAddress(value, { strict: false }), { message: "invalid address" });
14
+ /** A `0x`-prefixed hex string, as viem's `Hex`. */
15
+ const hexSchema = z.custom((value) => typeof value === "string" && isHex(value), { message: "invalid hex string" });
16
+ /**
17
+ * A record keyed by address. Spelled out here because zod types a record key
18
+ * by the schema's output, which the branded `Address` is not inferred as.
19
+ **/
20
+ function addressRecord(value) {
21
+ const key = z.string().refine((v) => isAddress(v, { strict: false }), { message: "invalid address" });
22
+ return z.record(key, value);
23
+ }
24
+ //#endregion
25
+ export { addressRecord, addressSchema, hexSchema };
@@ -0,0 +1,229 @@
1
+ import { createRawTx } from "../../../onchain/utils/createRawTx.js";
2
+ import { getNetworkType } from "../../../onchain/chain/chains.js";
3
+ import { AP_PRICE_FEED_COMPRESSOR } from "../../../onchain/constants/address-provider.js";
4
+ import { VERSION_RANGE_310 } from "../../../onchain/constants/versions.js";
5
+ import { ChainContractsRegister } from "../../../onchain/base/ChainContractsRegister.js";
6
+ import { OnchainSDK } from "../../../onchain/OnchainSDK.js";
7
+ import "../../../onchain/index.js";
8
+ import { PriceFeedNotInStoreError } from "../errors.js";
9
+ import { INSTANCE_MANAGER } from "../../utils/literals.js";
10
+ import { PriceFeedStoreContract } from "../../bindings/price-feed-store.js";
11
+ import "../../deployment/addresses.js";
12
+ import { AddressProviderContract } from "../../bindings/address-provider.js";
13
+ import { InstanceManagerContract } from "../../bindings/instance-manager.js";
14
+ import { convertRawTxToSafeMultisigTx, getSafeBatch } from "../../utils/governance/batch.js";
15
+ import { getUpdatablePriceFeeds } from "../../utils/price-update/get-updatable-feeds.js";
16
+ import { getFeedsToUpdate, updateBounds } from "./lp-price-feeds.js";
17
+ //#region src/permissionless/api/transactions/InstanceOwnerTransactions.ts
18
+ const lower = (value) => value.toLowerCase();
19
+ /**
20
+ * The Safe batches an instance owner executes to apply what a curator
21
+ * prepared: adding their private feeds to the PriceFeedStore, renaming feeds,
22
+ * changing staleness periods, forbidding feeds and refreshing LP bounds.
23
+ *
24
+ * Every batch is wrapped with `wrapConfigureLocal`, so the InstanceManager is
25
+ * the only caller the PriceFeedStore ever sees.
26
+ *
27
+ * Backend-free: a batch is built off the chain it will be executed on, and
28
+ * the store it reads is the one {@link PermissionlessOracles} already
29
+ * fetched. Nothing is sent either — a curator never executes these
30
+ * themselves. They prepare a batch and hand it to the instance owner, who
31
+ * reviews and executes it from their Safe.
32
+ *
33
+ * ```ts
34
+ * const txs = await permissionless.transactions.addFeeds({
35
+ * chainId: 1,
36
+ * owner: curator,
37
+ * });
38
+ * ```
39
+ **/
40
+ var InstanceOwnerTransactions = class {
41
+ #chains;
42
+ #oracles;
43
+ constructor(chains, oracles) {
44
+ this.#chains = chains;
45
+ this.#oracles = oracles;
46
+ }
47
+ /**
48
+ * The batch that adds the owner's private feeds to the store and allows
49
+ * them on the assets they were connected to. Only feeds that actually carry
50
+ * a connection are added: a feed nobody priced would land in the store
51
+ * doing nothing.
52
+ **/
53
+ async addFeeds({ chainId, owner }) {
54
+ const [batch, store] = await Promise.all([this.#batchContext(chainId), this.#oracles.store({ chainId })]);
55
+ const pairs = store.assets.flatMap((asset) => asset.priceFeeds.filter((entry) => entry.status === "private").map((entry) => ({
56
+ asset: asset.address,
57
+ priceFeed: entry.pricefeed.address
58
+ })));
59
+ const connected = new Set(pairs.map((pair) => lower(pair.priceFeed)));
60
+ const feedsToAdd = store.priceFeeds.filter((feed) => !feed.isInStore && connected.has(lower(feed.address)));
61
+ const txs = [...feedsToAdd.map((feed) => batch.store.addPriceFeedTx(feed.address, feed.stalenessPeriod, feed.name)), ...pairs.map((pair) => batch.store.allowPriceFeedTx(pair.asset, pair.priceFeed))];
62
+ return this.#envelope({
63
+ batch,
64
+ author: owner,
65
+ name: "pfs-updates",
66
+ txs,
67
+ touchedFeeds: feedsToAdd.map((feed) => feed.address)
68
+ });
69
+ }
70
+ /**
71
+ * The batch that renames feeds already in the store. A name is part of what
72
+ * the store holds, so changing one is a remove and a fresh add, followed by
73
+ * allowing the feed again on every asset that priced it.
74
+ **/
75
+ async changeNames({ chainId, owner, names }) {
76
+ const [batch, store] = await Promise.all([this.#batchContext(chainId), this.#oracles.store({ chainId })]);
77
+ const feedToAssets = await this.#feedToAssets(batch.store);
78
+ const inStore = new Map(store.priceFeeds.filter((feed) => feed.isInStore).map((feed) => [lower(feed.address), feed]));
79
+ const txs = [];
80
+ for (const [address, name] of Object.entries(names)) {
81
+ const feed = inStore.get(lower(address));
82
+ if (!feed) throw new PriceFeedNotInStoreError(address, chainId);
83
+ txs.push(batch.store.removePriceFeedTx(feed.address), batch.store.addPriceFeedTx(feed.address, feed.stalenessPeriod, name));
84
+ for (const asset of feedToAssets.get(lower(address)) ?? []) txs.push(batch.store.allowPriceFeedTx(asset, feed.address));
85
+ }
86
+ return this.#envelope({
87
+ batch,
88
+ author: owner,
89
+ name: "pricefeed-name-changes",
90
+ txs,
91
+ touchedFeeds: Object.keys(names)
92
+ });
93
+ }
94
+ /**
95
+ * The batch that changes how long each feed's price stays valid.
96
+ **/
97
+ async changeStalenessPeriods({ chainId, owner, periods }) {
98
+ const batch = await this.#batchContext(chainId);
99
+ const entries = Object.entries(periods);
100
+ const txs = entries.map(([address, period]) => batch.store.setStalenessPeriodTx(address, period));
101
+ return this.#envelope({
102
+ batch,
103
+ author: owner,
104
+ name: "pricefeed-staleness-changes",
105
+ txs,
106
+ touchedFeeds: entries.map(([address]) => address)
107
+ });
108
+ }
109
+ /**
110
+ * The batch that forbids feeds on the assets they were allowed for.
111
+ **/
112
+ async forbidFeeds({ chainId, owner, tokens }) {
113
+ const batch = await this.#batchContext(chainId);
114
+ const txs = Object.entries(tokens).flatMap(([token, feeds]) => feeds.map((feed) => createRawTx(batch.store.address, {
115
+ abi: batch.store.abi,
116
+ functionName: "forbidPriceFeed",
117
+ args: [token, feed]
118
+ })));
119
+ return this.#envelope({
120
+ batch,
121
+ author: owner,
122
+ name: "forbid-feeds",
123
+ txs,
124
+ touchedFeeds: []
125
+ });
126
+ }
127
+ /**
128
+ * The batch that pulls every drifted LP feed's lower bound back under its
129
+ * exchange rate. Unlike the others this takes no input: the whole store is
130
+ * scanned and only the feeds that drifted produce a transaction, so this
131
+ * one is slow.
132
+ **/
133
+ async updateBounds({ chainId, owner }) {
134
+ const batch = await this.#batchContext(chainId);
135
+ const pfCompressor = await this.#priceFeedCompressor(batch.client);
136
+ const known = await batch.store.getKnownPriceFeeds();
137
+ const feeds = await getFeedsToUpdate(batch.client, pfCompressor, known);
138
+ const configureTxs = [];
139
+ for (const feed of feeds) configureTxs.push(...await updateBounds(batch.client, feed));
140
+ const txs = [batch.store.configurePriceFeeds(configureTxs.map((tx) => ({
141
+ target: tx.to,
142
+ callData: tx.callData
143
+ })))];
144
+ return this.#envelope({
145
+ batch,
146
+ author: owner,
147
+ name: "update-bounds",
148
+ txs,
149
+ touchedFeeds: []
150
+ });
151
+ }
152
+ /**
153
+ * The contracts every batch of one chain is built against.
154
+ *
155
+ * Nothing here checks that the instance is activated: that is a backend
156
+ * read, and an instance without a deployed InstanceManager fails on the
157
+ * owner lookup below anyway.
158
+ **/
159
+ async #batchContext(chainId) {
160
+ const client = this.#chains.client(chainId);
161
+ const addressProvider = new AddressProviderContract("0xF7f0a609BfAb9a0A98786951ef10e5FE26cC1E38", client);
162
+ const instanceManager = new InstanceManagerContract(await addressProvider.getAddressOrRevert(INSTANCE_MANAGER), new ChainContractsRegister(client));
163
+ return {
164
+ chainId,
165
+ client,
166
+ store: new PriceFeedStoreContract("0x74A868AC479EE145029bB80827BB77F7B7c441cB", client),
167
+ instanceManager,
168
+ instanceOwner: await instanceManager.getOwner()
169
+ };
170
+ }
171
+ /** The common shape every batch is returned in. */
172
+ async #envelope(args) {
173
+ const { batch, author, name, txs, touchedFeeds } = args;
174
+ const { chainId, client, instanceManager, instanceOwner } = batch;
175
+ const wrapped = txs.map((tx) => instanceManager.wrapConfigureLocal(tx));
176
+ const safeBatch = getSafeBatch({
177
+ chainId,
178
+ safeAddress: instanceOwner,
179
+ name,
180
+ txs: wrapped.map((tx) => convertRawTxToSafeMultisigTx(tx))
181
+ });
182
+ const [block, updatableFeeds] = await Promise.all([client.getBlock(), this.#updatableFeeds(touchedFeeds, client)]);
183
+ return {
184
+ chainId,
185
+ author,
186
+ instanceManager: instanceManager.address,
187
+ batches: [safeBatch.transactions],
188
+ createdAtBlock: Number(block.number),
189
+ updatableFeeds: [updatableFeeds]
190
+ };
191
+ }
192
+ /** Which of the touched feeds the executor has to push a price update for. */
193
+ async #updatableFeeds(touchedFeeds, client) {
194
+ if (touchedFeeds.length === 0) return [];
195
+ const sdk = await this.#sdk(client);
196
+ return (await getUpdatablePriceFeeds({
197
+ sdk,
198
+ client,
199
+ pfCompressor: this.#compressorFrom(sdk),
200
+ priceFeeds: touchedFeeds
201
+ })).map((contract) => contract.address);
202
+ }
203
+ async #priceFeedCompressor(client) {
204
+ return this.#compressorFrom(await this.#sdk(client));
205
+ }
206
+ #compressorFrom(sdk) {
207
+ const [compressor] = sdk.addressProvider.mustGetLatest(AP_PRICE_FEED_COMPRESSOR, VERSION_RANGE_310);
208
+ return compressor;
209
+ }
210
+ async #sdk(client) {
211
+ const chainId = client.chain?.id ?? await client.getChainId();
212
+ const sdk = new OnchainSDK(getNetworkType(chainId), { client });
213
+ await sdk.attach({ marketConfigurators: [] });
214
+ return sdk;
215
+ }
216
+ /** Every asset each feed is currently allowed on, keyed by lowercase feed. */
217
+ async #feedToAssets(store) {
218
+ const byFeed = /* @__PURE__ */ new Map();
219
+ for (const { token, priceFeeds } of await store.getTokenPriceFeedsMap()) for (const feed of priceFeeds) {
220
+ const key = lower(feed);
221
+ const assets = byFeed.get(key);
222
+ if (assets) assets.push(token.toLowerCase());
223
+ else byFeed.set(key, [token.toLowerCase()]);
224
+ }
225
+ return byFeed;
226
+ }
227
+ };
228
+ //#endregion
229
+ export { InstanceOwnerTransactions };
@@ -0,0 +1,3 @@
1
+ import { InstanceOwnerTransactions } from "./InstanceOwnerTransactions.js";
2
+ import "./types.js";
3
+ export { InstanceOwnerTransactions };
@@ -0,0 +1,84 @@
1
+ import { createRawTx } from "../../../onchain/utils/createRawTx.js";
2
+ import { simulateMulticall } from "../../../onchain/utils/viem/simulateMulticall.js";
3
+ import { priceFeedCompressorAbi } from "../../../abi/compressors/priceFeedCompressor.js";
4
+ import "../../../onchain/index.js";
5
+ import { decodeFunctionResult, encodeFunctionData, parseAbi } from "viem";
6
+ //#region src/permissionless/api/transactions/lp-price-feeds.ts
7
+ const LOWER_BOUND_FACTOR = 999n;
8
+ const ilpPriceFeedAbi = parseAbi([
9
+ "function contractType() external view returns (bytes32)",
10
+ "function setLimiter(uint256 newLimiter) external",
11
+ "function getLPExchangeRate() public view returns (uint256 exchangeRate)",
12
+ "function lowerBound() external view returns (uint256)",
13
+ "function upperBound() external view returns (uint256)"
14
+ ]);
15
+ function currentLowerBound(client, address) {
16
+ return client.readContract({
17
+ abi: ilpPriceFeedAbi,
18
+ address,
19
+ functionName: "lowerBound"
20
+ });
21
+ }
22
+ function getValue(client, address) {
23
+ return client.readContract({
24
+ abi: ilpPriceFeedAbi,
25
+ address,
26
+ functionName: "getLPExchangeRate"
27
+ });
28
+ }
29
+ function toLowerBound(value) {
30
+ return value * LOWER_BOUND_FACTOR / 1000n;
31
+ }
32
+ /**
33
+ * Moves an LP feed's lower bound back under its current exchange rate, when
34
+ * the rate has outgrown the bound or drifted far enough from it to be worth a
35
+ * transaction. Returns nothing when the bound still fits.
36
+ **/
37
+ async function updateBounds(client, address) {
38
+ const value = await getValue(client, address);
39
+ const currentLowerBoundValue = await currentLowerBound(client, address);
40
+ const lowerBound = toLowerBound(value);
41
+ const deviationFromValue = Math.floor(Number(10000n * (value - currentLowerBoundValue) / currentLowerBoundValue)) / 1e4;
42
+ const deviationFromBound = Math.floor(Number(10000n * (lowerBound - currentLowerBoundValue) / currentLowerBoundValue)) / 1e4;
43
+ const txs = [];
44
+ if (deviationFromValue < 0 || Math.abs(deviationFromBound) > .005) txs.push(createRawTx(address, {
45
+ abi: ilpPriceFeedAbi,
46
+ functionName: "setLimiter",
47
+ args: [lowerBound]
48
+ }, `[${address}].setLimiter(${lowerBound}); // deviationFromValue: ${(100 * deviationFromValue).toFixed(2)}%`));
49
+ return txs;
50
+ }
51
+ /**
52
+ * Of the whole feed tree behind `feeds`, the ones that are LP feeds: the
53
+ * probe keeps whatever answers `getLPExchangeRate`.
54
+ **/
55
+ async function getFeedsToUpdate(client, pfCompressor, feeds) {
56
+ const updateableFeeds = /* @__PURE__ */ new Set();
57
+ const { data } = await client.call({
58
+ to: pfCompressor,
59
+ data: encodeFunctionData({
60
+ abi: priceFeedCompressorAbi,
61
+ functionName: "loadPriceFeedTree",
62
+ args: [feeds]
63
+ }),
64
+ gas: 200000000n
65
+ });
66
+ const trees = decodeFunctionResult({
67
+ abi: priceFeedCompressorAbi,
68
+ functionName: "loadPriceFeedTree",
69
+ data: data ?? "0x"
70
+ });
71
+ for (const tree of trees) updateableFeeds.add(tree.baseParams.addr.toLowerCase());
72
+ const candidates = Array.from(updateableFeeds);
73
+ const { results } = await simulateMulticall(client, {
74
+ contracts: candidates.map((feed) => ({
75
+ address: feed,
76
+ abi: ilpPriceFeedAbi,
77
+ functionName: "getLPExchangeRate"
78
+ })),
79
+ allowFailure: true
80
+ });
81
+ return candidates.filter((_, index) => results[index]?.status === "success");
82
+ }
83
+ //#endregion
84
+ export { getFeedsToUpdate, updateBounds };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -3,9 +3,9 @@ import { BaseContract } from "../../onchain/base/BaseContract.js";
3
3
  import "../../onchain/index.js";
4
4
  import { CROSS_CHAIN_MULTISIG } from "../utils/literals.js";
5
5
  import { normalizeSignature } from "../utils/signature.js";
6
- import { crossChainMultisigAbi } from "../../abi/310/crossChainMultisig.js";
7
6
  import "../deployment/addresses.js";
8
7
  import { InstanceManagerContract } from "./instance-manager.js";
8
+ import { crossChainMultisigAbi } from "../../abi/310/crossChainMultisig.js";
9
9
  import { MarketConfiguratorFactoryContract } from "./market-configurator-factory.js";
10
10
  import { parseAbi, parseEventLogs, recoverTypedDataAddress, zeroAddress } from "viem";
11
11
  //#region src/permissionless/bindings/cross-chain-multisig.ts
@@ -1,10 +1,10 @@
1
- import { AddressProviderContract } from "./address-provider.js";
2
1
  import { BytecodeRepositoryContract } from "./bytecode-repository.js";
2
+ import { priceFeedSetupParams } from "./pricefeeds/index.js";
3
+ import { PriceFeedStoreContract } from "./price-feed-store.js";
4
+ import { AddressProviderContract } from "./address-provider.js";
3
5
  import { TokenCompressorContract } from "./compressors/token-compressor.js";
4
6
  import { WithdrawalCompressorContract } from "./compressors/withdrawal-compressor.js";
5
7
  import "./compressors/index.js";
6
- import { priceFeedSetupParams } from "./pricefeeds/index.js";
7
- import { PriceFeedStoreContract } from "./price-feed-store.js";
8
8
  import { RoutingManagerContract } from "./router/routing-manager.js";
9
9
  import "./router/index.js";
10
10
  import { TreasurySplitterContract } from "./treasury-splitter.js";
@@ -3,8 +3,7 @@ import { BaseContract } from "../../onchain/base/BaseContract.js";
3
3
  import { gearboxRouterAbi } from "../../abi/router/gearboxRouter.js";
4
4
  import "../../onchain/index.js";
5
5
  import { BytecodeRepositoryContract } from "./bytecode-repository.js";
6
- import { WithdrawalCompressorContract } from "./compressors/withdrawal-compressor.js";
7
- import "./compressors/index.js";
6
+ import { PriceFeedStoreContract } from "./price-feed-store.js";
8
7
  import "../deployment/addresses.js";
9
8
  import { instanceManagerAbi } from "../../abi/310/instanceManager.js";
10
9
  import { camelotV3WorkerAbi } from "../../abi/router/camelotV3Worker.js";
@@ -13,7 +12,8 @@ import { mellow4626WorkerAbi } from "../../abi/router/mellow4626Worker.js";
13
12
  import { pendleRouterWorkerAbi } from "../../abi/router/pendleRouterWorker.js";
14
13
  import { uniswapV3WorkerAbi } from "../../abi/router/uniswapV3Worker.js";
15
14
  import { uniswapV4WorkerAbi } from "../../abi/router/uniswapV4Worker.js";
16
- import { PriceFeedStoreContract } from "./price-feed-store.js";
15
+ import { WithdrawalCompressorContract } from "./compressors/withdrawal-compressor.js";
16
+ import "./compressors/index.js";
17
17
  import { RoutingManagerContract } from "./router/routing-manager.js";
18
18
  import "./router/index.js";
19
19
  import { TreasurySplitterContract } from "./treasury-splitter.js";
@@ -1,15 +1,27 @@
1
- import { AddressProviderContract } from "./bindings/address-provider.js";
1
+ import { PermissionlessChainUnreachableError, PermissionlessNotAttachedError, PriceFeedNotInStoreError, PriceFeedSaltMissingError, PriceFeedStalenessUnknownError } from "./api/errors.js";
2
+ import { ChainsNamespace } from "./api/chains/ChainsNamespace.js";
3
+ import { deriveEffectiveStalenessPeriod } from "./api/deploy/effective-staleness.js";
2
4
  import { BYTECODE_REPOSITORY, CROSS_CHAIN_GOVERNANCE, CROSS_CHAIN_MULTISIG, INSTANCE_MANAGER, MARKET_CONFIGURATOR_FACTORY, PRICE_FEED_STORE, TOKEN_COMPRESSOR } from "./utils/literals.js";
3
5
  import { normalizeSignature } from "./utils/signature.js";
4
6
  import { BytecodeRepositoryContract } from "./bindings/bytecode-repository.js";
5
- import { TokenCompressorContract } from "./bindings/compressors/token-compressor.js";
6
- import { WithdrawalCompressorContract } from "./bindings/compressors/withdrawal-compressor.js";
7
- import { Addresses } from "./deployment/addresses.js";
8
7
  import { priceFeedSetupParams } from "./bindings/pricefeeds/index.js";
9
8
  import { PriceFeedStoreContract } from "./bindings/price-feed-store.js";
9
+ import { Addresses } from "./deployment/addresses.js";
10
+ import { encodeFunctionParams } from "./utils/abi-encoder.js";
11
+ import { DEFAULT_DEPLOY_SALT, PermissionlessDeploy, priceFeedSalt } from "./api/deploy/PermissionlessDeploy.js";
12
+ import { getPrices } from "./utils/price-update/get-prices.js";
13
+ import { GET_PRICES_CHUNK_SIZE, GET_PRICES_GAS_LIMIT_BY_CHAIN_ID, PermissionlessOracles } from "./api/oracles/PermissionlessOracles.js";
14
+ import { AddressProviderContract } from "./bindings/address-provider.js";
15
+ import { TokenCompressorContract } from "./bindings/compressors/token-compressor.js";
16
+ import { WithdrawalCompressorContract } from "./bindings/compressors/withdrawal-compressor.js";
10
17
  import { RoutingManagerContract } from "./bindings/router/routing-manager.js";
11
18
  import { TreasurySplitterContract } from "./bindings/treasury-splitter.js";
12
19
  import { InstanceManagerContract } from "./bindings/instance-manager.js";
20
+ import { calculateChecksum, convertRawTxToSafeMultisigTx, getSafeBatch, getSafeBatches } from "./utils/governance/batch.js";
21
+ import { getUpdatablePriceFeeds } from "./utils/price-update/get-updatable-feeds.js";
22
+ import { InstanceOwnerTransactions } from "./api/transactions/InstanceOwnerTransactions.js";
23
+ import { GearboxPermissionless } from "./api/GearboxPermissionless.js";
24
+ import "./api/index.js";
13
25
  import { MarketConfiguratorFactoryContract } from "./bindings/market-configurator-factory.js";
14
26
  import { CrossChainMultisigContract } from "./bindings/cross-chain-multisig.js";
15
27
  import { PUBLIC_CREATE2_FACTORY, checkCreate2Deployment, checkCreate2DeploymentAddress, createCreate2DeployRawTx, deployUsingPublicCreate2, getCreate2AddressPublicFactory, getCreate2DeploymentAddress, handleSalt } from "./utils/create2.js";
@@ -24,12 +36,8 @@ import { ArchiveTransport } from "./chains/archive-transport.js";
24
36
  import { chunkedLogsTransport } from "./chains/chunked-log-transport.js";
25
37
  import "./core/index.js";
26
38
  import { MAINNET_CCM_CONSTRUCTOR_PARAMS, MAINNET_DEPLOYMENT_BLOCK, MAINNET_DEPLOYMENT_CCM_SALT, MAINNET_DEPLOYMENT_IM_SALT } from "./deployment/mainnet.js";
27
- import { encodeFunctionParams } from "./utils/abi-encoder.js";
28
39
  import { getBlockNumberByTimestamp } from "./utils/block-utils.js";
29
- import { calculateChecksum, convertRawTxToSafeMultisigTx, getSafeBatch, getSafeBatches } from "./utils/governance/batch.js";
30
40
  import { convertQueueBatchToExecuteTx } from "./utils/governance/timelock-txs.js";
31
41
  import { getPriceUpdateTx } from "./utils/price-update/get-price-update-tx.js";
32
- import { getPrices } from "./utils/price-update/get-prices.js";
33
- import { getUpdatablePriceFeeds } from "./utils/price-update/get-updatable-feeds.js";
34
42
  import "./utils/index.js";
35
- export { AccessMode, AddressProviderContract, Addresses, ArchiveTransport, BYTECODE_REPOSITORY, BytecodeRepositoryContract, CROSS_CHAIN_GOVERNANCE, CROSS_CHAIN_MULTISIG, CrossChainMultisigContract, GovernorContract, INSTANCE_MANAGER, InstanceManagerContract, MAINNET_CCM_CONSTRUCTOR_PARAMS, MAINNET_DEPLOYMENT_BLOCK, MAINNET_DEPLOYMENT_CCM_SALT, MAINNET_DEPLOYMENT_IM_SALT, MARKET_CONFIGURATOR_FACTORY, MarketConfiguratorContract, MarketConfiguratorFactoryContract, PRICE_FEED_STORE, PUBLIC_CREATE2_FACTORY, PriceFeedStoreContract, RoutingManagerContract, TOKEN_COMPRESSOR, TimeLockContract, TokenCompressorContract, TreasurySplitterContract, WithdrawalCompressorContract, calculateChecksum, checkCreate2Deployment, checkCreate2DeploymentAddress, chunkedLogsTransport, convertPercent, convertQueueBatchToExecuteTx, convertRawTxToSafeMultisigTx, createCallData, createCreate2DeployRawTx, deepJsonParse, deployUsingPublicCreate2, encodeFunctionParams, formatBytecodeSize, formatBytecodeVersion, getBlockNumberByTimestamp, getCreate2AddressPublicFactory, getCreate2DeploymentAddress, getPriceUpdateTx, getPrices, getSafeBatch, getSafeBatches, getUpdatablePriceFeeds, handleSalt, normalizeSignature, priceFeedSetupParams, shortenHash, significantTrunc };
43
+ export { AccessMode, AddressProviderContract, Addresses, ArchiveTransport, BYTECODE_REPOSITORY, BytecodeRepositoryContract, CROSS_CHAIN_GOVERNANCE, CROSS_CHAIN_MULTISIG, ChainsNamespace, CrossChainMultisigContract, DEFAULT_DEPLOY_SALT, GET_PRICES_CHUNK_SIZE, GET_PRICES_GAS_LIMIT_BY_CHAIN_ID, GearboxPermissionless, GovernorContract, INSTANCE_MANAGER, InstanceManagerContract, InstanceOwnerTransactions, MAINNET_CCM_CONSTRUCTOR_PARAMS, MAINNET_DEPLOYMENT_BLOCK, MAINNET_DEPLOYMENT_CCM_SALT, MAINNET_DEPLOYMENT_IM_SALT, MARKET_CONFIGURATOR_FACTORY, MarketConfiguratorContract, MarketConfiguratorFactoryContract, PRICE_FEED_STORE, PUBLIC_CREATE2_FACTORY, PermissionlessChainUnreachableError, PermissionlessDeploy, PermissionlessNotAttachedError, PermissionlessOracles, PriceFeedNotInStoreError, PriceFeedSaltMissingError, PriceFeedStalenessUnknownError, PriceFeedStoreContract, RoutingManagerContract, TOKEN_COMPRESSOR, TimeLockContract, TokenCompressorContract, TreasurySplitterContract, WithdrawalCompressorContract, calculateChecksum, checkCreate2Deployment, checkCreate2DeploymentAddress, chunkedLogsTransport, convertPercent, convertQueueBatchToExecuteTx, convertRawTxToSafeMultisigTx, createCallData, createCreate2DeployRawTx, deepJsonParse, deployUsingPublicCreate2, deriveEffectiveStalenessPeriod, encodeFunctionParams, formatBytecodeSize, formatBytecodeVersion, getBlockNumberByTimestamp, getCreate2AddressPublicFactory, getCreate2DeploymentAddress, getPriceUpdateTx, getPrices, getSafeBatch, getSafeBatches, getUpdatablePriceFeeds, handleSalt, normalizeSignature, priceFeedSalt, priceFeedSetupParams, shortenHash, significantTrunc };
@@ -1,7 +1,7 @@
1
1
  import { createRawTx } from "../../../onchain/utils/createRawTx.js";
2
2
  import "../../../onchain/index.js";
3
- import { governorAbi } from "../../../abi/governance/governor.js";
4
3
  import { convertRawTxToSafeMultisigTx } from "./batch.js";
4
+ import { governorAbi } from "../../../abi/governance/governor.js";
5
5
  //#region src/permissionless/utils/governance/timelock-txs.ts
6
6
  function convertQueueBatchToExecuteTx(queueBatch) {
7
7
  const executionBatch = queueBatch.filter((tx) => tx.contractMethod.name === "queueTransaction").map((tx) => ({
@@ -1,14 +1,14 @@
1
1
  import { BYTECODE_REPOSITORY, CROSS_CHAIN_GOVERNANCE, CROSS_CHAIN_MULTISIG, INSTANCE_MANAGER, MARKET_CONFIGURATOR_FACTORY, PRICE_FEED_STORE, TOKEN_COMPRESSOR } from "./literals.js";
2
2
  import { normalizeSignature } from "./signature.js";
3
+ import { encodeFunctionParams } from "./abi-encoder.js";
4
+ import { getPrices } from "./price-update/get-prices.js";
5
+ import { calculateChecksum, convertRawTxToSafeMultisigTx, getSafeBatch, getSafeBatches } from "./governance/batch.js";
6
+ import { getUpdatablePriceFeeds } from "./price-update/get-updatable-feeds.js";
3
7
  import { PUBLIC_CREATE2_FACTORY, checkCreate2Deployment, checkCreate2DeploymentAddress, createCreate2DeployRawTx, deployUsingPublicCreate2, getCreate2AddressPublicFactory, getCreate2DeploymentAddress, handleSalt } from "./create2.js";
4
8
  import { convertPercent, deepJsonParse, formatBytecodeSize, formatBytecodeVersion, shortenHash, significantTrunc } from "./format.js";
5
- import { encodeFunctionParams } from "./abi-encoder.js";
6
9
  import { getBlockNumberByTimestamp } from "./block-utils.js";
7
- import { calculateChecksum, convertRawTxToSafeMultisigTx, getSafeBatch, getSafeBatches } from "./governance/batch.js";
8
10
  import { convertQueueBatchToExecuteTx } from "./governance/timelock-txs.js";
9
11
  import "./governance/index.js";
10
12
  import { getPriceUpdateTx } from "./price-update/get-price-update-tx.js";
11
- import { getPrices } from "./price-update/get-prices.js";
12
- import { getUpdatablePriceFeeds } from "./price-update/get-updatable-feeds.js";
13
13
  import "./price-update/index.js";
14
14
  export { BYTECODE_REPOSITORY, CROSS_CHAIN_GOVERNANCE, CROSS_CHAIN_MULTISIG, INSTANCE_MANAGER, MARKET_CONFIGURATOR_FACTORY, PRICE_FEED_STORE, PUBLIC_CREATE2_FACTORY, TOKEN_COMPRESSOR, calculateChecksum, checkCreate2Deployment, checkCreate2DeploymentAddress, convertPercent, convertQueueBatchToExecuteTx, convertRawTxToSafeMultisigTx, createCreate2DeployRawTx, deepJsonParse, deployUsingPublicCreate2, encodeFunctionParams, formatBytecodeSize, formatBytecodeVersion, getBlockNumberByTimestamp, getCreate2AddressPublicFactory, getCreate2DeploymentAddress, getPriceUpdateTx, getPrices, getSafeBatch, getSafeBatches, getUpdatablePriceFeeds, handleSalt, normalizeSignature, shortenHash, significantTrunc };
@@ -2,8 +2,8 @@ import { createRawTx } from "../../../onchain/utils/createRawTx.js";
2
2
  import { getRawPriceUpdates } from "../../../onchain/market/pricefeeds/updates/getRawPriceUpdates.js";
3
3
  import { OnchainSDK } from "../../../onchain/OnchainSDK.js";
4
4
  import "../../../onchain/index.js";
5
- import "../../deployment/addresses.js";
6
5
  import { PriceFeedStoreContract } from "../../bindings/price-feed-store.js";
6
+ import "../../deployment/addresses.js";
7
7
  import "../../bindings/index.js";
8
8
  import { multicall3Abi } from "viem";
9
9
  //#region src/permissionless/utils/price-update/get-price-update-tx.ts
@@ -1,4 +1,4 @@
1
- import { getPriceUpdateTx } from "./get-price-update-tx.js";
2
1
  import { getPrices } from "./get-prices.js";
3
2
  import { getUpdatablePriceFeeds } from "./get-updatable-feeds.js";
3
+ import { getPriceUpdateTx } from "./get-price-update-tx.js";
4
4
  export { getPriceUpdateTx, getPrices, getUpdatablePriceFeeds };
@@ -54,6 +54,18 @@ declare abstract class AbstractOffchainNamespace {
54
54
  * schema skew throw, since none of them is a {@link DataResponse}.
55
55
  **/
56
56
  protected get<S extends z.ZodType>(request: OffchainGetRequest<S>): Promise<DataResponse<z.output<S>>>;
57
+ /**
58
+ * Reads one endpoint that answers with the payload alone, and returns it
59
+ * unwrapped.
60
+ *
61
+ * A read served at no particular block has no envelope to report: the
62
+ * permissionless routes either span every chain at once, or fall through to
63
+ * a multicall on the chain itself, so the backend answers `{ data }` and
64
+ * there is no {@link ResponseMetadata} for {@link get} to decode. The
65
+ * envelope is still there, which is what keeps a payload that happens to be
66
+ * an array from being mistaken for an error body.
67
+ **/
68
+ protected getData<S extends z.ZodType>(request: OffchainGetRequest<S>): Promise<z.output<S>>;
57
69
  /**
58
70
  * Reads the charts of one subject: one series per metric named, onto the one
59
71
  * grid that lets them be compared at an index.
@@ -0,0 +1,71 @@
1
+ import { GearboxPermissionlessOptions } from "./types.js";
2
+ import { AttachChainsArgs } from "./chains/types.js";
3
+ import { ChainsNamespace } from "./chains/ChainsNamespace.js";
4
+ import { PermissionlessDeploy } from "./deploy/PermissionlessDeploy.js";
5
+ import { PermissionlessOracles } from "./oracles/PermissionlessOracles.js";
6
+ import { InstanceOwnerTransactions } from "./transactions/InstanceOwnerTransactions.js";
7
+ //#region src/permissionless/api/GearboxPermissionless.d.ts
8
+ /**
9
+ * Client for the permissionless stack: the oracle rows of a chain, the
10
+ * batches an instance owner executes, and the deploys that produce what goes
11
+ * into both.
12
+ *
13
+ * It reads the same backend {@link GearboxAPI} does, and reads the same way —
14
+ * one namespace per subject, every call scoped by the chain it names. Which
15
+ * chains those are is not passed in: {@link attach} reads the list off the
16
+ * backend and builds a client for each, so this client covers exactly what
17
+ * the backend serves.
18
+ *
19
+ * ```ts
20
+ * const permissionless = new GearboxPermissionless({
21
+ * baseUrl: "https://api.gearbox.fi",
22
+ * });
23
+ * await permissionless.attach();
24
+ *
25
+ * const [chain] = permissionless.chains.list();
26
+ * const store = await permissionless.oracles.store({ chainId: chain.chainId });
27
+ * ```
28
+ *
29
+ * Only what needs a server goes to one. {@link chains} and {@link oracles}
30
+ * are the backend's reads; {@link deploy} and {@link transactions} read the
31
+ * target chain directly, because everything they answer is derived from there
32
+ * and a round trip would only move the derivation further from the wallet
33
+ * that has to sign for it.
34
+ **/
35
+ declare class GearboxPermissionless {
36
+ /**
37
+ * Namespace for the chains the stack runs on, and the viem clients that
38
+ * reach them.
39
+ **/
40
+ readonly chains: ChainsNamespace;
41
+ /**
42
+ * Namespace for price feeds: the store and its prices.
43
+ **/
44
+ readonly oracles: PermissionlessOracles;
45
+ /**
46
+ * Namespace for the Safe batches an instance owner executes. Backend-free,
47
+ * see {@link InstanceOwnerTransactions}.
48
+ **/
49
+ readonly transactions: InstanceOwnerTransactions;
50
+ /**
51
+ * Namespace for deploys through the BytecodeRepository. Backend-free, see
52
+ * {@link PermissionlessDeploy}.
53
+ **/
54
+ readonly deploy: PermissionlessDeploy;
55
+ constructor(options?: GearboxPermissionlessOptions);
56
+ /**
57
+ * Loads the chain list and builds the clients, see
58
+ * {@link ChainsNamespace.attach}. Idempotent, and joins a call already in
59
+ * flight.
60
+ *
61
+ * Everything that reads a chain goes through it, so this has to finish
62
+ * before the first such call.
63
+ **/
64
+ attach(args?: AttachChainsArgs): Promise<void>;
65
+ /**
66
+ * Whether {@link attach} has completed.
67
+ **/
68
+ get isAttached(): boolean;
69
+ }
70
+ //#endregion
71
+ export { GearboxPermissionless };