@gearbox-protocol/sdk 17.2.0-next.1 → 17.2.1
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/onchain/accounts/intents/maxBorrow.js +10 -12
- package/dist/cjs/onchain/accounts/intents/testing/sdk-mock.js +0 -1
- package/dist/cjs/onchain/chain/chains.js +1 -0
- package/dist/cjs/onchain/market/credit/CreditSuite.js +3 -43
- package/dist/cjs/onchain/market/pool/PoolQuotaKeeperV310Contract.js +1 -4
- package/dist/cjs/rewards/RewardsService.js +48 -0
- package/dist/cjs/rewards/errors.js +15 -4
- package/dist/cjs/rewards/helpers.js +88 -0
- package/dist/cjs/rewards/index.js +3 -4
- package/dist/cjs/rewards/merkl-api.js +14 -25
- package/dist/cjs/rewards/toMerklRewards.js +21 -76
- package/dist/cjs/rewards/toTurtleRewards.js +61 -0
- package/dist/cjs/rewards/turtle-api.js +67 -0
- package/dist/cjs/rewards/types.js +1 -0
- package/dist/esm/onchain/accounts/intents/maxBorrow.js +10 -12
- package/dist/esm/onchain/accounts/intents/testing/sdk-mock.js +0 -1
- package/dist/esm/onchain/chain/chains.js +1 -0
- package/dist/esm/onchain/market/credit/CreditSuite.js +3 -43
- package/dist/esm/onchain/market/pool/PoolQuotaKeeperV310Contract.js +1 -4
- package/dist/esm/rewards/RewardsService.js +47 -0
- package/dist/esm/rewards/errors.js +15 -5
- package/dist/esm/rewards/helpers.js +83 -0
- package/dist/esm/rewards/index.js +3 -4
- package/dist/esm/rewards/merkl-api.js +15 -25
- package/dist/esm/rewards/toMerklRewards.js +22 -77
- package/dist/esm/rewards/toTurtleRewards.js +60 -0
- package/dist/esm/rewards/turtle-api.js +64 -0
- package/dist/esm/rewards/types.js +1 -0
- package/dist/types/model/errors/operation-errors.d.ts +1 -6
- package/dist/types/onchain/accounts/intents/maxBorrow.d.ts +9 -11
- package/dist/types/onchain/market/credit/CreditSuite.d.ts +1 -20
- package/dist/types/onchain/market/pool/PoolQuotaKeeperV310Contract.d.ts +0 -2
- package/dist/types/rewards/RewardsService.d.ts +29 -0
- package/dist/types/rewards/errors.d.ts +8 -3
- package/dist/types/rewards/helpers.d.ts +44 -0
- package/dist/types/rewards/index.d.ts +6 -4
- package/dist/types/rewards/merkl-api.d.ts +5 -10
- package/dist/types/rewards/toMerklRewards.d.ts +6 -37
- package/dist/types/rewards/toTurtleRewards.d.ts +10 -0
- package/dist/types/rewards/turtle-api.d.ts +66 -0
- package/dist/types/rewards/types.d.ts +41 -0
- package/package.json +1 -1
- package/dist/cjs/rewards/multichain.js +0 -40
- package/dist/esm/rewards/multichain.js +0 -39
- package/dist/types/rewards/multichain.d.ts +0 -33
|
@@ -30,18 +30,16 @@ interface MaxBorrowProps {
|
|
|
30
30
|
* prices, under its liquidation threshold, capped by the quota the borrow
|
|
31
31
|
* buys for it, all of which is {@link collateralValuation}'s business. The ceiling
|
|
32
32
|
* is then held to what the market will actually lend: the pool's free
|
|
33
|
-
* liquidity, the manager's own allowance
|
|
34
|
-
*
|
|
33
|
+
* liquidity, the manager's own allowance and the facade's `maxDebt`, whichever
|
|
34
|
+
* binds first.
|
|
35
35
|
*
|
|
36
|
-
* The facade's `minDebt` is not applied
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* is under `minDebt` is different: `maxStrategyBorrowAmount` answers `0n`,
|
|
44
|
-
* because no loan of any size exists there.
|
|
36
|
+
* The facade's `minDebt` is deliberately not applied. It is a floor, and a
|
|
37
|
+
* ceiling answered as `0n` because the collateral is too small for this market
|
|
38
|
+
* would tell a form nothing about what it is holding — the number a user needs
|
|
39
|
+
* to see is the one they are short of. Collateral that carries something
|
|
40
|
+
* therefore answers with it, whether or not the market would lend that little;
|
|
41
|
+
* a loan under the floor is refused by `borrow` itself, with `debtOutOfRange`
|
|
42
|
+
* naming both ends.
|
|
45
43
|
*
|
|
46
44
|
* Nothing is fetched or simulated — the account does not exist yet and every
|
|
47
45
|
* input is loaded market state, so a form can call this on each keystroke.
|
|
@@ -194,7 +194,7 @@ declare class CreditSuite extends SDKConstruct {
|
|
|
194
194
|
*/
|
|
195
195
|
isForbidden(token: Address): boolean;
|
|
196
196
|
/**
|
|
197
|
-
* Largest debt
|
|
197
|
+
* Largest debt one new position can take from this credit manager right now,
|
|
198
198
|
* and which limit set that number.
|
|
199
199
|
*
|
|
200
200
|
* Minimum of:
|
|
@@ -203,27 +203,8 @@ declare class CreditSuite extends SDKConstruct {
|
|
|
203
203
|
* - the facade's per-account `maxDebt`.
|
|
204
204
|
* While `maxDebtPerBlockMultiplier` is `0` the facade
|
|
205
205
|
* takes no new debt at all, so the answer is `0`.
|
|
206
|
-
*
|
|
207
|
-
* These are the bounds every debt increase answers to, an existing account's
|
|
208
|
-
* included, which is what the guards hold a simulation to. Opening a position
|
|
209
|
-
* answers to two more — see {@link maxStrategyBorrowAmount}.
|
|
210
206
|
*/
|
|
211
207
|
maxBorrowAmount(): MaxBorrowAmount;
|
|
212
|
-
/**
|
|
213
|
-
* Largest debt one new position can take from this credit manager right now,
|
|
214
|
-
* and which limit set that number.
|
|
215
|
-
*
|
|
216
|
-
* {@link maxBorrowAmount} held to the two bounds only a position being opened
|
|
217
|
-
* answers to: the remaining quota of the strategy target collateral, which
|
|
218
|
-
* the position has to buy to be worth anything, and the facade's `minDebt`,
|
|
219
|
-
* which a first debt cannot sit under. `amount` is `0` whenever no position
|
|
220
|
-
* can be opened right now, and `limit` names why.
|
|
221
|
-
*
|
|
222
|
-
* An operation on an account that already exists is held to neither: its
|
|
223
|
-
* quota is weighed against the token its own plan buys, and its debt is
|
|
224
|
-
* already over the floor, so a top-up smaller than `minDebt` is legal.
|
|
225
|
-
*/
|
|
226
|
-
maxStrategyBorrowAmount(): MaxBorrowAmount;
|
|
227
208
|
/**
|
|
228
209
|
* The single target collateral of this suite's strategy, or `undefined` when
|
|
229
210
|
* none can be resolved.
|
|
@@ -494,8 +494,6 @@ declare class PoolQuotaKeeperV310Contract extends BaseContract<abi> implements I
|
|
|
494
494
|
/**
|
|
495
495
|
* How much more quota the market will take for a token, in the underlying.
|
|
496
496
|
* `0n` when the market has no quota entry; not the same as {@link hasActiveQuota}.
|
|
497
|
-
* Never negative: a limit lowered under what is already quoted leaves no
|
|
498
|
-
* room, not a debt.
|
|
499
497
|
*/
|
|
500
498
|
quotaAvailable(token: Address): bigint;
|
|
501
499
|
/**
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ChainId } from "../model/primitives.js";
|
|
2
|
+
import { DataResponse } from "../model/response.js";
|
|
3
|
+
import "../model/index.js";
|
|
4
|
+
import { PluginsMap } from "../onchain/plugins/types.js";
|
|
5
|
+
import { MultichainSDK } from "../onchain/MultichainSDK.js";
|
|
6
|
+
import { MultichainConstruct } from "../onchain/base/MultichainConstruct.js";
|
|
7
|
+
import "../onchain/index.js";
|
|
8
|
+
import { Reward } from "./types.js";
|
|
9
|
+
import { Address } from "viem";
|
|
10
|
+
//#region src/rewards/RewardsService.d.ts
|
|
11
|
+
interface RewardsServiceKeys {
|
|
12
|
+
/** Raises Merkl's rate limit; the keyless path answers too. */
|
|
13
|
+
merklApiKey?: string;
|
|
14
|
+
/** Turtle is skipped without one: its API answers no keyless request. */
|
|
15
|
+
turtleApiKey?: string;
|
|
16
|
+
}
|
|
17
|
+
declare class RewardsService<const Plugins extends PluginsMap = {}> extends MultichainConstruct<Plugins> {
|
|
18
|
+
#private;
|
|
19
|
+
constructor(sdk: MultichainSDK<Plugins>, keys?: RewardsServiceKeys);
|
|
20
|
+
/**
|
|
21
|
+
* Every claimable reward a wallet holds — Merkl campaigns and the Gearbox
|
|
22
|
+
* organisation's Turtle streams — across the chains the handle carries.
|
|
23
|
+
* A chain is `status: "error"` only when every source failed on it; a chain
|
|
24
|
+
* with nothing to claim is a `"success"` with no rewards.
|
|
25
|
+
**/
|
|
26
|
+
list(wallet: Address, chainIds?: ChainId[]): Promise<DataResponse<Reward[]>>;
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { RewardsService };
|
|
@@ -3,7 +3,7 @@ import "../model/index.js";
|
|
|
3
3
|
import { BaseError } from "viem";
|
|
4
4
|
//#region src/rewards/errors.d.ts
|
|
5
5
|
/**
|
|
6
|
-
* Thrown when
|
|
6
|
+
* Thrown when Merkl did not answer for a chain.
|
|
7
7
|
*
|
|
8
8
|
* Everything a reader needs is in the message: this error travels to consumers
|
|
9
9
|
* inside a chain's {@link ChainFailed} metadata, where it is typed `unknown`
|
|
@@ -12,7 +12,12 @@ import { BaseError } from "viem";
|
|
|
12
12
|
declare class MerklRequestFailedError extends BaseError {
|
|
13
13
|
name: string;
|
|
14
14
|
readonly chainId: ChainId;
|
|
15
|
-
constructor(chainId: ChainId, path: string,
|
|
15
|
+
constructor(chainId: ChainId, path: string, cause: unknown);
|
|
16
|
+
}
|
|
17
|
+
/** Turtle answers for every chain at once, so this names no chain. */
|
|
18
|
+
declare class TurtleRequestFailedError extends BaseError {
|
|
19
|
+
name: string;
|
|
20
|
+
constructor(path: string, cause: unknown);
|
|
16
21
|
}
|
|
17
22
|
//#endregion
|
|
18
|
-
export { MerklRequestFailedError };
|
|
23
|
+
export { MerklRequestFailedError, TurtleRequestFailedError };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Token } from "../model/primitives.js";
|
|
2
|
+
import "../model/index.js";
|
|
3
|
+
import { MerklReward, RewardsSdk } from "./types.js";
|
|
4
|
+
import { Address } from "viem";
|
|
5
|
+
//#region src/rewards/helpers.d.ts
|
|
6
|
+
/** A claimable amount of one token in one pool, before it is merged. */
|
|
7
|
+
interface RewardPart {
|
|
8
|
+
pool: Address;
|
|
9
|
+
poolToken: Token;
|
|
10
|
+
token: Token;
|
|
11
|
+
value: bigint;
|
|
12
|
+
/** USD price of one whole token, as the source sends it. */
|
|
13
|
+
price: number | string | null | undefined;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The pool a source names, and its share token. A v3.1 pool is its own
|
|
17
|
+
* ERC-4626 share token, so its address is the only token a campaign can name;
|
|
18
|
+
* the `AddressMap` owns the casing a source writes it in.
|
|
19
|
+
*/
|
|
20
|
+
declare function resolvePool(sdk: RewardsSdk): (address: string | undefined) => {
|
|
21
|
+
pool: `0x${string}`;
|
|
22
|
+
poolToken: Token;
|
|
23
|
+
} | undefined;
|
|
24
|
+
/** Sources send amounts as free-form strings, which `toBigInt` throws on. */
|
|
25
|
+
declare function parseAmount(value: string | undefined): bigint | undefined;
|
|
26
|
+
/** What is left of `total` after `claimed`, when anything is. */
|
|
27
|
+
declare function remaining(total: bigint | undefined, claimed: bigint | undefined): bigint | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* An incentive token is rarely protocol collateral, so the registry usually
|
|
30
|
+
* has no entry for it — and both sources always name it.
|
|
31
|
+
*/
|
|
32
|
+
declare function toRewardToken(sdk: RewardsSdk, address: Address, named: {
|
|
33
|
+
symbol: string;
|
|
34
|
+
name?: string;
|
|
35
|
+
decimals: number;
|
|
36
|
+
}): Token;
|
|
37
|
+
/**
|
|
38
|
+
* One reward per pool and incentive token, at the last part's price. Amounts
|
|
39
|
+
* are summed raw and priced once at the end — pricing each part and adding the results would round
|
|
40
|
+
* every one of them.
|
|
41
|
+
*/
|
|
42
|
+
declare function mergeRewards(sdk: RewardsSdk, source: MerklReward["source"], parts: readonly RewardPart[]): MerklReward[];
|
|
43
|
+
//#endregion
|
|
44
|
+
export { RewardPart, mergeRewards, parseAmount, remaining, resolvePool, toRewardToken };
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
1
|
+
import { MerklReward, PointsReward, Reward } from "./types.js";
|
|
2
|
+
import { RewardsService } from "./RewardsService.js";
|
|
3
|
+
import { MerklRequestFailedError, TurtleRequestFailedError } from "./errors.js";
|
|
4
|
+
import { MerkleXYZUserRewardsV4Response } from "./merkl-api.js";
|
|
5
|
+
import { TurtleWalletRewards } from "./turtle-api.js";
|
|
6
|
+
export { MerklRequestFailedError, type MerklReward, type MerkleXYZUserRewardsV4Response, type PointsReward, type Reward, RewardsService, TurtleRequestFailedError, type TurtleWalletRewards };
|
|
@@ -38,10 +38,6 @@ interface MerkleXYZChain {
|
|
|
38
38
|
name: string;
|
|
39
39
|
icon: string;
|
|
40
40
|
}
|
|
41
|
-
/**
|
|
42
|
-
* Merkl's own host and the Angle mirror, tried in this order.
|
|
43
|
-
*/
|
|
44
|
-
declare const MERKL_DOMAINS: readonly ["https://api.merkl.xyz", "https://api-merkl.angle.money"];
|
|
45
41
|
declare const MERKL_API_KEY_HEADER = "X-API-Key";
|
|
46
42
|
interface FetchMerklUserRewardsProps {
|
|
47
43
|
chainId: ChainId;
|
|
@@ -53,12 +49,11 @@ interface FetchMerklUserRewardsProps {
|
|
|
53
49
|
/**
|
|
54
50
|
* The wallet's raw Merkl rewards on one chain.
|
|
55
51
|
*
|
|
56
|
-
* Rejects with {@link MerklRequestFailedError} when
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* was never established.
|
|
52
|
+
* Rejects with {@link MerklRequestFailedError} when Merkl does not answer, so a
|
|
53
|
+
* caller can tell an unreachable Merkl from a wallet with nothing to claim. A
|
|
54
|
+
* non-2xx counts as no answer: it carries no rewards either way, and treating
|
|
55
|
+
* it as success would report emptiness that was never established.
|
|
61
56
|
*/
|
|
62
57
|
declare function fetchMerklUserRewards({ chainId, user, apiKey }: FetchMerklUserRewardsProps): Promise<MerkleXYZUserRewardsV4Response>;
|
|
63
58
|
//#endregion
|
|
64
|
-
export { FetchMerklUserRewardsProps, MERKL_API_KEY_HEADER,
|
|
59
|
+
export { FetchMerklUserRewardsProps, MERKL_API_KEY_HEADER, MerkleXYZUserRewardsV4, MerkleXYZUserRewardsV4Response, fetchMerklUserRewards };
|
|
@@ -1,42 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import "../model/index.js";
|
|
3
|
-
import { OnchainSDK } from "../onchain/OnchainSDK.js";
|
|
4
|
-
import "../onchain/index.js";
|
|
1
|
+
import { MerklReward, RewardsSdk } from "./types.js";
|
|
5
2
|
import { MerkleXYZUserRewardsV4Response } from "./merkl-api.js";
|
|
6
|
-
import { Address } from "viem";
|
|
7
3
|
//#region src/rewards/toMerklRewards.d.ts
|
|
8
4
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* reassembles one out of the loose fields Merkl sends.
|
|
5
|
+
* Merkl's answer for one chain, one reward per pool and incentive token.
|
|
6
|
+
* A breakdown Merkl cannot be read from is skipped rather than thrown on: it
|
|
7
|
+
* must not sink the chain, which the caller would then be told is unreachable.
|
|
13
8
|
*/
|
|
14
|
-
|
|
15
|
-
readonly chainId: ChainId;
|
|
16
|
-
/** Market pool whose depositors the campaign rewards. */
|
|
17
|
-
readonly pool: Address;
|
|
18
|
-
/** That pool's share token — what the campaign is keyed on. */
|
|
19
|
-
readonly poolToken: Token;
|
|
20
|
-
/**
|
|
21
|
-
* The incentive token being handed out, how much of it is claimable
|
|
22
|
-
* (distributed minus already claimed, always > 0) and what that is worth.
|
|
23
|
-
*
|
|
24
|
-
* Priced by Merkl, not by the market oracles: a campaign's incentive token
|
|
25
|
-
* is rarely collateral in the pool it incentivises, so the oracles usually
|
|
26
|
-
* do not know it — GEAR, which most Gearbox campaigns pay in, among them.
|
|
27
|
-
* `valueUsd` is `null` for a token Merkl does not price either.
|
|
28
|
-
*/
|
|
29
|
-
readonly amount: TokenAmount;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* What the mapping needs off a chain's SDK: which chain the rows belong to,
|
|
33
|
-
* the pools a campaign can be keyed on, and the registry that names their
|
|
34
|
-
* tokens. Nothing else, and nothing asynchronous.
|
|
35
|
-
*/
|
|
36
|
-
type MerklRewardsSdk = Pick<OnchainSDK, "chainId" | "marketRegister" | "tokensMeta">;
|
|
37
|
-
/**
|
|
38
|
-
* Merkl's answer for one chain, turned into rows of the read model.
|
|
39
|
-
*/
|
|
40
|
-
declare function toMerklRewards(sdk: MerklRewardsSdk, response: MerkleXYZUserRewardsV4Response): MerklReward[];
|
|
9
|
+
declare function toMerklRewards(sdk: RewardsSdk, response: MerkleXYZUserRewardsV4Response): MerklReward[];
|
|
41
10
|
//#endregion
|
|
42
|
-
export {
|
|
11
|
+
export { toMerklRewards };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Reward, RewardsSdk } from "./types.js";
|
|
2
|
+
import { TurtleWalletRewards } from "./turtle-api.js";
|
|
3
|
+
//#region src/rewards/toTurtleRewards.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* The streams targeting a pool on the SDK's chain, merged per pool and
|
|
6
|
+
* incentive. A token reward is what is committed and not yet claimed.
|
|
7
|
+
*/
|
|
8
|
+
declare function toTurtleRewards(sdk: RewardsSdk, { streams, proofs }: TurtleWalletRewards, claimed: ReadonlyMap<string, bigint>): Reward[];
|
|
9
|
+
//#endregion
|
|
10
|
+
export { toTurtleRewards };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { OnchainSDK } from "../onchain/OnchainSDK.js";
|
|
2
|
+
import "../onchain/index.js";
|
|
3
|
+
import { Address } from "viem";
|
|
4
|
+
//#region src/rewards/turtle-api.d.ts
|
|
5
|
+
interface TurtleWalletStream {
|
|
6
|
+
streamId: string;
|
|
7
|
+
snapshots: Array<{
|
|
8
|
+
rewardsAccumulated: string;
|
|
9
|
+
}>;
|
|
10
|
+
stream: {
|
|
11
|
+
orgId: string;
|
|
12
|
+
contractAddress: Address | null;
|
|
13
|
+
/** For Gearbox the target is a pool's share token. */
|
|
14
|
+
customArgs: {
|
|
15
|
+
targetToken?: {
|
|
16
|
+
address: Address;
|
|
17
|
+
chain: {
|
|
18
|
+
chainId: string;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
point?: {
|
|
23
|
+
id: string;
|
|
24
|
+
name: string;
|
|
25
|
+
decimals: number;
|
|
26
|
+
} | null;
|
|
27
|
+
rewardToken: {
|
|
28
|
+
address: Address;
|
|
29
|
+
symbol: string;
|
|
30
|
+
name: string;
|
|
31
|
+
decimals: number;
|
|
32
|
+
} | null;
|
|
33
|
+
lastSnapshot: {
|
|
34
|
+
rewardTokenPrice: string | null;
|
|
35
|
+
} | null;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
interface TurtleMerkleProof {
|
|
39
|
+
streamId: string;
|
|
40
|
+
chainId: number;
|
|
41
|
+
contractAddress: Address;
|
|
42
|
+
/** Cumulative committed allocation, not what is left to claim. */
|
|
43
|
+
amount: string;
|
|
44
|
+
}
|
|
45
|
+
interface TurtleWalletRewards {
|
|
46
|
+
streams: TurtleWalletStream[];
|
|
47
|
+
proofs: TurtleMerkleProof[];
|
|
48
|
+
}
|
|
49
|
+
declare const turtleStreamAbi: readonly [{
|
|
50
|
+
readonly type: "function";
|
|
51
|
+
readonly name: "getClaimedRewards";
|
|
52
|
+
readonly stateMutability: "view";
|
|
53
|
+
readonly inputs: readonly [{
|
|
54
|
+
readonly name: "user";
|
|
55
|
+
readonly type: "address";
|
|
56
|
+
}];
|
|
57
|
+
readonly outputs: readonly [{
|
|
58
|
+
readonly name: "";
|
|
59
|
+
readonly type: "uint256";
|
|
60
|
+
}];
|
|
61
|
+
}];
|
|
62
|
+
declare function fetchTurtleWalletRewards(user: Address, apiKey: string): Promise<TurtleWalletRewards>;
|
|
63
|
+
/** What each of the wallet's streams on the chain has paid out, at the latest block. */
|
|
64
|
+
declare function readTurtleClaimed(sdk: OnchainSDK, user: Address, { proofs }: TurtleWalletRewards): Promise<Map<string, bigint>>;
|
|
65
|
+
//#endregion
|
|
66
|
+
export { TurtleMerkleProof, TurtleWalletRewards, TurtleWalletStream, fetchTurtleWalletRewards, readTurtleClaimed, turtleStreamAbi };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ChainId, Token, TokenAmount } from "../model/primitives.js";
|
|
2
|
+
import { PointsProgramPnL } from "../model/positions.js";
|
|
3
|
+
import "../model/index.js";
|
|
4
|
+
import { OnchainSDK } from "../onchain/OnchainSDK.js";
|
|
5
|
+
import "../onchain/index.js";
|
|
6
|
+
import { Address } from "viem";
|
|
7
|
+
//#region src/rewards/types.d.ts
|
|
8
|
+
/**
|
|
9
|
+
* One claimable token reward, denominated and priced.
|
|
10
|
+
*
|
|
11
|
+
* Both tokens arrive resolved, so a consumer neither looks one up nor
|
|
12
|
+
* reassembles one out of the loose fields a source sends.
|
|
13
|
+
*/
|
|
14
|
+
interface MerklReward {
|
|
15
|
+
/** Where the reward is claimed. */
|
|
16
|
+
readonly source: "merkl" | "turtle";
|
|
17
|
+
readonly chainId: ChainId;
|
|
18
|
+
/** Market pool whose depositors the campaign rewards. */
|
|
19
|
+
readonly pool: Address;
|
|
20
|
+
/** That pool's share token — what the campaign is keyed on. */
|
|
21
|
+
readonly poolToken: Token;
|
|
22
|
+
/**
|
|
23
|
+
* The incentive token being handed out, how much of it is claimable
|
|
24
|
+
* (distributed minus already claimed, always > 0) and what that is worth.
|
|
25
|
+
*
|
|
26
|
+
* Priced by the source, not by the market oracles: a campaign's incentive
|
|
27
|
+
* token is rarely collateral in the pool it incentivises, so the oracles
|
|
28
|
+
* usually do not know it — GEAR, which most Gearbox campaigns pay in, among
|
|
29
|
+
* them. `valueUsd` is `null` for a token the source does not price either.
|
|
30
|
+
*/
|
|
31
|
+
readonly amount: TokenAmount;
|
|
32
|
+
}
|
|
33
|
+
/** Points have no token and no price, and are not claimed. */
|
|
34
|
+
interface PointsReward extends Omit<MerklReward, "amount"> {
|
|
35
|
+
readonly points: PointsProgramPnL;
|
|
36
|
+
}
|
|
37
|
+
type Reward = MerklReward | PointsReward;
|
|
38
|
+
/** What the mapping needs off a chain's SDK, and nothing asynchronous. */
|
|
39
|
+
type RewardsSdk = Pick<OnchainSDK, "chainId" | "marketRegister" | "tokensMeta">;
|
|
40
|
+
//#endregion
|
|
41
|
+
export { MerklReward, PointsReward, Reward, RewardsSdk };
|
package/package.json
CHANGED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_onchain_base_MultichainConstruct = require("../onchain/base/MultichainConstruct.js");
|
|
3
|
-
require("../onchain/index.js");
|
|
4
|
-
const require_rewards_merkl_api = require("./merkl-api.js");
|
|
5
|
-
const require_rewards_toMerklRewards = require("./toMerklRewards.js");
|
|
6
|
-
let viem = require("viem");
|
|
7
|
-
//#region src/rewards/multichain.ts
|
|
8
|
-
/**
|
|
9
|
-
* The fan-out itself. Private because rewards are not an SDK namespace yet:
|
|
10
|
-
* the read is a free function, and this is only how it reaches `queryChains`.
|
|
11
|
-
**/
|
|
12
|
-
var MerklRewardsFanOut = class extends require_onchain_base_MultichainConstruct.MultichainConstruct {
|
|
13
|
-
async list(wallet, chainIds, apiKey) {
|
|
14
|
-
const user = (0, viem.getAddress)(wallet);
|
|
15
|
-
return this.queryChains({
|
|
16
|
-
chainIds,
|
|
17
|
-
label: "list rewards",
|
|
18
|
-
block: "state",
|
|
19
|
-
run: async (sdk) => require_rewards_toMerklRewards.toMerklRewards(sdk, await require_rewards_merkl_api.fetchMerklUserRewards({
|
|
20
|
-
chainId: sdk.chainId,
|
|
21
|
-
user,
|
|
22
|
-
apiKey
|
|
23
|
-
}))
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
/**
|
|
28
|
-
* Every claimable Merkl reward a wallet holds, across the chains the handle
|
|
29
|
-
* carries.
|
|
30
|
-
*
|
|
31
|
-
* Answers the read model's own envelope, so a chain that could not be reached
|
|
32
|
-
* is `status: "error"` in `meta.chains` while a chain with nothing to claim is
|
|
33
|
-
* a `"success"` that contributed no rows. That distinction is the point: the
|
|
34
|
-
* single-chain read this replaces resolved empty either way.
|
|
35
|
-
**/
|
|
36
|
-
async function getMerklRewardsMultichain({ sdk, wallet, chainIds, apiKey }) {
|
|
37
|
-
return new MerklRewardsFanOut(sdk).list(wallet, chainIds, apiKey);
|
|
38
|
-
}
|
|
39
|
-
//#endregion
|
|
40
|
-
exports.getMerklRewardsMultichain = getMerklRewardsMultichain;
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { MultichainConstruct } from "../onchain/base/MultichainConstruct.js";
|
|
2
|
-
import "../onchain/index.js";
|
|
3
|
-
import { fetchMerklUserRewards } from "./merkl-api.js";
|
|
4
|
-
import { toMerklRewards } from "./toMerklRewards.js";
|
|
5
|
-
import { getAddress } from "viem";
|
|
6
|
-
//#region src/rewards/multichain.ts
|
|
7
|
-
/**
|
|
8
|
-
* The fan-out itself. Private because rewards are not an SDK namespace yet:
|
|
9
|
-
* the read is a free function, and this is only how it reaches `queryChains`.
|
|
10
|
-
**/
|
|
11
|
-
var MerklRewardsFanOut = class extends MultichainConstruct {
|
|
12
|
-
async list(wallet, chainIds, apiKey) {
|
|
13
|
-
const user = getAddress(wallet);
|
|
14
|
-
return this.queryChains({
|
|
15
|
-
chainIds,
|
|
16
|
-
label: "list rewards",
|
|
17
|
-
block: "state",
|
|
18
|
-
run: async (sdk) => toMerklRewards(sdk, await fetchMerklUserRewards({
|
|
19
|
-
chainId: sdk.chainId,
|
|
20
|
-
user,
|
|
21
|
-
apiKey
|
|
22
|
-
}))
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* Every claimable Merkl reward a wallet holds, across the chains the handle
|
|
28
|
-
* carries.
|
|
29
|
-
*
|
|
30
|
-
* Answers the read model's own envelope, so a chain that could not be reached
|
|
31
|
-
* is `status: "error"` in `meta.chains` while a chain with nothing to claim is
|
|
32
|
-
* a `"success"` that contributed no rows. That distinction is the point: the
|
|
33
|
-
* single-chain read this replaces resolved empty either way.
|
|
34
|
-
**/
|
|
35
|
-
async function getMerklRewardsMultichain({ sdk, wallet, chainIds, apiKey }) {
|
|
36
|
-
return new MerklRewardsFanOut(sdk).list(wallet, chainIds, apiKey);
|
|
37
|
-
}
|
|
38
|
-
//#endregion
|
|
39
|
-
export { getMerklRewardsMultichain };
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { ChainId } from "../model/primitives.js";
|
|
2
|
-
import { DataResponse } from "../model/response.js";
|
|
3
|
-
import "../model/index.js";
|
|
4
|
-
import { PluginsMap } from "../onchain/plugins/types.js";
|
|
5
|
-
import { MultichainSDK } from "../onchain/MultichainSDK.js";
|
|
6
|
-
import "../onchain/index.js";
|
|
7
|
-
import { MerklReward } from "./toMerklRewards.js";
|
|
8
|
-
import { Address } from "viem";
|
|
9
|
-
//#region src/rewards/multichain.d.ts
|
|
10
|
-
interface GetMerklRewardsMultichainProps<Plugins extends PluginsMap = {}> {
|
|
11
|
-
/** Handle whose chains are asked. */
|
|
12
|
-
sdk: MultichainSDK<Plugins>;
|
|
13
|
-
/** Wallet whose claimable rewards to list. */
|
|
14
|
-
wallet: Address;
|
|
15
|
-
/**
|
|
16
|
-
* Chains to ask, defaulting to every chain the handle carries.
|
|
17
|
-
**/
|
|
18
|
-
chainIds?: ChainId[];
|
|
19
|
-
/** Raises Merkl's rate limit; the keyless path answers too. */
|
|
20
|
-
apiKey?: string;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Every claimable Merkl reward a wallet holds, across the chains the handle
|
|
24
|
-
* carries.
|
|
25
|
-
*
|
|
26
|
-
* Answers the read model's own envelope, so a chain that could not be reached
|
|
27
|
-
* is `status: "error"` in `meta.chains` while a chain with nothing to claim is
|
|
28
|
-
* a `"success"` that contributed no rows. That distinction is the point: the
|
|
29
|
-
* single-chain read this replaces resolved empty either way.
|
|
30
|
-
**/
|
|
31
|
-
declare function getMerklRewardsMultichain<const Plugins extends PluginsMap = {}>({ sdk, wallet, chainIds, apiKey }: GetMerklRewardsMultichainProps<Plugins>): Promise<DataResponse<MerklReward[]>>;
|
|
32
|
-
//#endregion
|
|
33
|
-
export { GetMerklRewardsMultichainProps, getMerklRewardsMultichain };
|