@gearbox-protocol/sdk 14.10.6 → 14.11.0-next.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/abi/errors.js +42 -2
- package/dist/cjs/preview/index.js +26 -0
- package/dist/cjs/preview/package.json +1 -0
- package/dist/cjs/preview/parse/classifyInnerOperations.js +130 -0
- package/dist/cjs/preview/parse/errors.js +47 -0
- package/dist/cjs/preview/parse/index.js +32 -0
- package/dist/cjs/preview/parse/parseCreditFacadeOperation.js +111 -0
- package/dist/cjs/preview/parse/parsePoolOperation.js +62 -0
- package/dist/cjs/preview/parse/parseTransaction.js +46 -0
- package/dist/cjs/preview/parse/types.js +30 -0
- package/dist/cjs/preview/prerequisites/AllowancePrerequisite.js +78 -0
- package/dist/cjs/preview/prerequisites/BalancePrerequisite.js +77 -0
- package/dist/cjs/preview/prerequisites/Prerequisite.js +85 -0
- package/dist/cjs/preview/prerequisites/buildPrerequisites.js +141 -0
- package/dist/cjs/preview/prerequisites/index.js +32 -0
- package/dist/cjs/preview/prerequisites/runPrerequisites.js +71 -0
- package/dist/cjs/preview/prerequisites/types.js +16 -0
- package/dist/cjs/preview/simulate/decodeSimulationError.js +64 -0
- package/dist/cjs/preview/simulate/extractERC20Transfers.js +47 -0
- package/dist/cjs/preview/simulate/index.js +28 -0
- package/dist/cjs/preview/simulate/simulatePoolOperation.js +94 -0
- package/dist/cjs/preview/simulate/types.js +16 -0
- package/dist/esm/abi/errors.js +40 -1
- package/dist/esm/preview/index.js +3 -0
- package/dist/esm/preview/package.json +1 -0
- package/dist/esm/preview/parse/classifyInnerOperations.js +108 -0
- package/dist/esm/preview/parse/errors.js +22 -0
- package/dist/esm/preview/parse/index.js +6 -0
- package/dist/esm/preview/parse/parseCreditFacadeOperation.js +91 -0
- package/dist/esm/preview/parse/parsePoolOperation.js +38 -0
- package/dist/esm/preview/parse/parseTransaction.js +25 -0
- package/dist/esm/preview/parse/types.js +6 -0
- package/dist/esm/preview/prerequisites/AllowancePrerequisite.js +57 -0
- package/dist/esm/preview/prerequisites/BalancePrerequisite.js +56 -0
- package/dist/esm/preview/prerequisites/Prerequisite.js +63 -0
- package/dist/esm/preview/prerequisites/buildPrerequisites.js +117 -0
- package/dist/esm/preview/prerequisites/index.js +6 -0
- package/dist/esm/preview/prerequisites/runPrerequisites.js +47 -0
- package/dist/esm/preview/prerequisites/types.js +0 -0
- package/dist/esm/preview/simulate/decodeSimulationError.js +44 -0
- package/dist/esm/preview/simulate/extractERC20Transfers.js +23 -0
- package/dist/esm/preview/simulate/index.js +4 -0
- package/dist/esm/preview/simulate/simulatePoolOperation.js +70 -0
- package/dist/esm/preview/simulate/types.js +0 -0
- package/dist/types/abi/errors.d.ts +57 -0
- package/dist/types/preview/index.d.ts +3 -0
- package/dist/types/preview/parse/classifyInnerOperations.d.ts +21 -0
- package/dist/types/preview/parse/errors.d.ts +17 -0
- package/dist/types/preview/parse/index.d.ts +6 -0
- package/dist/types/preview/parse/parseCreditFacadeOperation.d.ts +18 -0
- package/dist/types/preview/parse/parsePoolOperation.d.ts +15 -0
- package/dist/types/preview/parse/parseTransaction.d.ts +23 -0
- package/dist/types/preview/parse/types.d.ts +78 -0
- package/dist/types/preview/prerequisites/AllowancePrerequisite.d.ts +24 -0
- package/dist/types/preview/prerequisites/BalancePrerequisite.d.ts +23 -0
- package/dist/types/preview/prerequisites/Prerequisite.d.ts +60 -0
- package/dist/types/preview/prerequisites/buildPrerequisites.d.ts +16 -0
- package/dist/types/preview/prerequisites/index.d.ts +6 -0
- package/dist/types/preview/prerequisites/runPrerequisites.d.ts +12 -0
- package/dist/types/preview/prerequisites/types.d.ts +78 -0
- package/dist/types/preview/simulate/decodeSimulationError.d.ts +18 -0
- package/dist/types/preview/simulate/extractERC20Transfers.d.ts +11 -0
- package/dist/types/preview/simulate/index.d.ts +4 -0
- package/dist/types/preview/simulate/simulatePoolOperation.d.ts +30 -0
- package/dist/types/preview/simulate/types.d.ts +43 -0
- package/package.json +6 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
async function verifyPrerequisites(prereqs, ctx) {
|
|
2
|
+
if (prereqs.length === 0) {
|
|
3
|
+
return [];
|
|
4
|
+
}
|
|
5
|
+
const ranges = [];
|
|
6
|
+
const calls = [];
|
|
7
|
+
for (const prereq of prereqs) {
|
|
8
|
+
const start = calls.length;
|
|
9
|
+
calls.push(...prereq.calls(ctx));
|
|
10
|
+
ranges.push({ start, end: calls.length });
|
|
11
|
+
}
|
|
12
|
+
let results;
|
|
13
|
+
try {
|
|
14
|
+
results = await ctx.sdk.client.multicall({
|
|
15
|
+
allowFailure: true,
|
|
16
|
+
contracts: calls,
|
|
17
|
+
// `undefined` lets viem read at `latest`; `blockNumber` is only set for
|
|
18
|
+
// testnet forks pinned to a specific block.
|
|
19
|
+
blockNumber: ctx.blockNumber
|
|
20
|
+
});
|
|
21
|
+
} catch (cause) {
|
|
22
|
+
const error = cause instanceof Error ? cause : new Error(String(cause));
|
|
23
|
+
return prereqs.map(
|
|
24
|
+
(prereq, i) => (
|
|
25
|
+
// Each prereq pairs its own kind with its detail, so the widened
|
|
26
|
+
// `resolve` return is safe to narrow back to the discriminated union.
|
|
27
|
+
prereq.resolve(
|
|
28
|
+
failureSlice(ranges[i].end - ranges[i].start, error)
|
|
29
|
+
)
|
|
30
|
+
)
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return prereqs.map(
|
|
34
|
+
(prereq, i) => prereq.resolve(
|
|
35
|
+
results.slice(ranges[i].start, ranges[i].end)
|
|
36
|
+
)
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
function failureSlice(n, error) {
|
|
40
|
+
return Array.from({ length: n }, () => ({
|
|
41
|
+
status: "failure",
|
|
42
|
+
error
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
export {
|
|
46
|
+
verifyPrerequisites
|
|
47
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BaseError,
|
|
3
|
+
ContractFunctionRevertedError,
|
|
4
|
+
decodeErrorResult
|
|
5
|
+
} from "viem";
|
|
6
|
+
import { errorAbis } from "../../abi/errors.js";
|
|
7
|
+
function decodeSimulationError(revert) {
|
|
8
|
+
const { error, data } = revert;
|
|
9
|
+
if (data && data !== "0x") {
|
|
10
|
+
try {
|
|
11
|
+
const decoded = decodeErrorResult({ abi: errorAbis, data });
|
|
12
|
+
return {
|
|
13
|
+
reason: formatDecodedError(decoded.errorName, decoded.args),
|
|
14
|
+
cause: error
|
|
15
|
+
};
|
|
16
|
+
} catch {
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if (error instanceof BaseError) {
|
|
20
|
+
const reverted = error.walk(
|
|
21
|
+
(e) => e instanceof ContractFunctionRevertedError
|
|
22
|
+
);
|
|
23
|
+
if (reverted instanceof ContractFunctionRevertedError) {
|
|
24
|
+
return {
|
|
25
|
+
reason: reverted.data?.errorName ?? reverted.reason ?? reverted.shortMessage ?? "reverted",
|
|
26
|
+
cause: error
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
return { reason: error.shortMessage ?? error.name, cause: error };
|
|
30
|
+
}
|
|
31
|
+
if (error instanceof Error) {
|
|
32
|
+
return { reason: error.message, cause: error };
|
|
33
|
+
}
|
|
34
|
+
return { reason: "reverted", cause: error };
|
|
35
|
+
}
|
|
36
|
+
function formatDecodedError(errorName, args) {
|
|
37
|
+
if (!args || args.length === 0) {
|
|
38
|
+
return errorName;
|
|
39
|
+
}
|
|
40
|
+
return `${errorName}(${args.map((arg) => String(arg)).join(", ")})`;
|
|
41
|
+
}
|
|
42
|
+
export {
|
|
43
|
+
decodeSimulationError
|
|
44
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { isAddressEqual, parseEventLogs } from "viem";
|
|
2
|
+
import { ierc20Abi } from "../../abi/iERC20.js";
|
|
3
|
+
function extractERC20Transfers(logs, watch) {
|
|
4
|
+
const parsed = parseEventLogs({
|
|
5
|
+
abi: ierc20Abi,
|
|
6
|
+
eventName: "Transfer",
|
|
7
|
+
logs
|
|
8
|
+
});
|
|
9
|
+
const transfers = [];
|
|
10
|
+
for (const log of parsed) {
|
|
11
|
+
const { from, to, value } = log.args;
|
|
12
|
+
const involved = watch.some(
|
|
13
|
+
(address) => isAddressEqual(from, address) || isAddressEqual(to, address)
|
|
14
|
+
);
|
|
15
|
+
if (involved) {
|
|
16
|
+
transfers.push({ token: log.address, amount: value, from, to });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return transfers;
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
extractERC20Transfers
|
|
23
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { isAddressEqual } from "viem";
|
|
2
|
+
import { simulateCalls } from "viem/actions";
|
|
3
|
+
import { ierc20Abi } from "../../abi/iERC20.js";
|
|
4
|
+
import { decodeSimulationError } from "./decodeSimulationError.js";
|
|
5
|
+
import { extractERC20Transfers } from "./extractERC20Transfers.js";
|
|
6
|
+
async function simulatePoolOperation(input) {
|
|
7
|
+
const { sdk, operation, to, calldata, wallet, blockNumber } = input;
|
|
8
|
+
const { underlying, pool } = operation;
|
|
9
|
+
const receiverIsWallet = isAddressEqual(operation.receiver, wallet);
|
|
10
|
+
const holders = receiverIsWallet ? [wallet] : [wallet, operation.receiver];
|
|
11
|
+
const tokens = [underlying, pool];
|
|
12
|
+
const balanceOf = (token, holder) => ({
|
|
13
|
+
to: token,
|
|
14
|
+
abi: ierc20Abi,
|
|
15
|
+
functionName: "balanceOf",
|
|
16
|
+
args: [holder]
|
|
17
|
+
});
|
|
18
|
+
const balanceCalls = holders.flatMap(
|
|
19
|
+
(holder) => tokens.map((token) => balanceOf(token, holder))
|
|
20
|
+
);
|
|
21
|
+
const { results } = await simulateCalls(sdk.client, {
|
|
22
|
+
account: wallet,
|
|
23
|
+
// `undefined` lets viem simulate at `latest`; `blockNumber` is only set for
|
|
24
|
+
// testnet forks pinned to a specific block.
|
|
25
|
+
blockNumber,
|
|
26
|
+
calls: [...balanceCalls, { to, data: calldata }, ...balanceCalls]
|
|
27
|
+
});
|
|
28
|
+
const sim = results;
|
|
29
|
+
const txIndex = balanceCalls.length;
|
|
30
|
+
const afterOffset = txIndex + 1;
|
|
31
|
+
const txResult = sim[txIndex];
|
|
32
|
+
if (!txResult || txResult.status === "failure") {
|
|
33
|
+
return {
|
|
34
|
+
status: "failure",
|
|
35
|
+
error: decodeSimulationError({
|
|
36
|
+
error: txResult?.error,
|
|
37
|
+
data: txResult?.data
|
|
38
|
+
})
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const balanceChanges = [];
|
|
42
|
+
for (const [holderIndex, address] of holders.entries()) {
|
|
43
|
+
const changes = [];
|
|
44
|
+
for (const [tokenIndex, token] of tokens.entries()) {
|
|
45
|
+
const slot = holderIndex * tokens.length + tokenIndex;
|
|
46
|
+
const before = readBalance(sim[slot]);
|
|
47
|
+
const after = readBalance(sim[afterOffset + slot]);
|
|
48
|
+
const delta = after - before;
|
|
49
|
+
const magnitude = delta >= 0n ? delta : -delta;
|
|
50
|
+
if (magnitude > 1n) {
|
|
51
|
+
changes.push({ token, before, after, delta });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (changes.length > 0) {
|
|
55
|
+
balanceChanges.push({ address, changes });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
status: "success",
|
|
60
|
+
transfers: extractERC20Transfers(txResult.logs ?? [], holders),
|
|
61
|
+
balanceChanges,
|
|
62
|
+
gasUsed: txResult.gasUsed
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function readBalance(result) {
|
|
66
|
+
return result?.status === "success" ? result.result : 0n;
|
|
67
|
+
}
|
|
68
|
+
export {
|
|
69
|
+
simulatePoolOperation
|
|
70
|
+
};
|
|
File without changes
|
|
@@ -629,6 +629,35 @@ export declare const iERC20ErrorsAbi: readonly [{
|
|
|
629
629
|
readonly internalType: "address";
|
|
630
630
|
}];
|
|
631
631
|
}];
|
|
632
|
+
export declare const safeERC20ErrorsAbi: readonly [{
|
|
633
|
+
readonly type: "error";
|
|
634
|
+
readonly name: "ForceApproveFailed";
|
|
635
|
+
readonly inputs: readonly [];
|
|
636
|
+
}, {
|
|
637
|
+
readonly type: "error";
|
|
638
|
+
readonly name: "Permit2TransferAmountTooHigh";
|
|
639
|
+
readonly inputs: readonly [];
|
|
640
|
+
}, {
|
|
641
|
+
readonly type: "error";
|
|
642
|
+
readonly name: "SafeDecreaseAllowanceFailed";
|
|
643
|
+
readonly inputs: readonly [];
|
|
644
|
+
}, {
|
|
645
|
+
readonly type: "error";
|
|
646
|
+
readonly name: "SafeIncreaseAllowanceFailed";
|
|
647
|
+
readonly inputs: readonly [];
|
|
648
|
+
}, {
|
|
649
|
+
readonly type: "error";
|
|
650
|
+
readonly name: "SafePermitBadLength";
|
|
651
|
+
readonly inputs: readonly [];
|
|
652
|
+
}, {
|
|
653
|
+
readonly type: "error";
|
|
654
|
+
readonly name: "SafeTransferFailed";
|
|
655
|
+
readonly inputs: readonly [];
|
|
656
|
+
}, {
|
|
657
|
+
readonly type: "error";
|
|
658
|
+
readonly name: "SafeTransferFromFailed";
|
|
659
|
+
readonly inputs: readonly [];
|
|
660
|
+
}];
|
|
632
661
|
export declare const errorAbis: readonly [{
|
|
633
662
|
readonly type: "error";
|
|
634
663
|
readonly name: "ERC20InsufficientAllowance";
|
|
@@ -693,6 +722,34 @@ export declare const errorAbis: readonly [{
|
|
|
693
722
|
readonly type: "address";
|
|
694
723
|
readonly internalType: "address";
|
|
695
724
|
}];
|
|
725
|
+
}, {
|
|
726
|
+
readonly type: "error";
|
|
727
|
+
readonly name: "ForceApproveFailed";
|
|
728
|
+
readonly inputs: readonly [];
|
|
729
|
+
}, {
|
|
730
|
+
readonly type: "error";
|
|
731
|
+
readonly name: "Permit2TransferAmountTooHigh";
|
|
732
|
+
readonly inputs: readonly [];
|
|
733
|
+
}, {
|
|
734
|
+
readonly type: "error";
|
|
735
|
+
readonly name: "SafeDecreaseAllowanceFailed";
|
|
736
|
+
readonly inputs: readonly [];
|
|
737
|
+
}, {
|
|
738
|
+
readonly type: "error";
|
|
739
|
+
readonly name: "SafeIncreaseAllowanceFailed";
|
|
740
|
+
readonly inputs: readonly [];
|
|
741
|
+
}, {
|
|
742
|
+
readonly type: "error";
|
|
743
|
+
readonly name: "SafePermitBadLength";
|
|
744
|
+
readonly inputs: readonly [];
|
|
745
|
+
}, {
|
|
746
|
+
readonly type: "error";
|
|
747
|
+
readonly name: "SafeTransferFailed";
|
|
748
|
+
readonly inputs: readonly [];
|
|
749
|
+
}, {
|
|
750
|
+
readonly type: "error";
|
|
751
|
+
readonly name: "SafeTransferFromFailed";
|
|
752
|
+
readonly inputs: readonly [];
|
|
696
753
|
}, {
|
|
697
754
|
readonly type: "error";
|
|
698
755
|
readonly name: "ActiveCreditAccountNotSetException";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type Address } from "viem";
|
|
2
|
+
import type { InnerOperation } from "../../history/index.js";
|
|
3
|
+
import type { OnchainSDK, ParsedCallV2 } from "../../sdk/index.js";
|
|
4
|
+
export interface ClassifyInnerOperationsProps {
|
|
5
|
+
sdk: OnchainSDK;
|
|
6
|
+
/** Underlying token of the credit manager, used for debt operations. */
|
|
7
|
+
underlying: Address;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Calldata-only counterpart of the SDK's `classifyMulticallOperations`.
|
|
11
|
+
*
|
|
12
|
+
* Maps each inner multicall entry to an {@link InnerOperation}:
|
|
13
|
+
* - adapter targets become an `Execute` {@link AdapterOperation};
|
|
14
|
+
* - credit-facade self-calls map to the matching inner facade operation;
|
|
15
|
+
* - unknown targets fall back to a generic `Execute`.
|
|
16
|
+
*
|
|
17
|
+
* Since raw calldata has no execution trace, `transfers` is always empty and
|
|
18
|
+
* `legacy` is a zeroed placeholder; protocol-level fields mirror the adapter
|
|
19
|
+
* call.
|
|
20
|
+
*/
|
|
21
|
+
export declare function classifyInnerOperations(calls: ParsedCallV2[], props: ClassifyInnerOperationsProps): InnerOperation[];
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Address } from "viem";
|
|
2
|
+
/**
|
|
3
|
+
* Thrown when the target of a transaction is neither a known Gearbox pool nor a
|
|
4
|
+
* credit facade.
|
|
5
|
+
*/
|
|
6
|
+
export declare class UnsupportedTargetError extends Error {
|
|
7
|
+
readonly target: Address;
|
|
8
|
+
constructor(target: Address);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Thrown when a pool call uses a function other than ERC4626 `deposit`/`redeem`.
|
|
12
|
+
*/
|
|
13
|
+
export declare class UnsupportedPoolFunctionError extends Error {
|
|
14
|
+
readonly pool: Address;
|
|
15
|
+
readonly functionName: string;
|
|
16
|
+
constructor(pool: Address, functionName: string);
|
|
17
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type Hex } from "viem";
|
|
2
|
+
import type { OuterFacadeOperation } from "../../history/index.js";
|
|
3
|
+
import type { CreditFacadeV310Contract, OnchainSDK } from "../../sdk/index.js";
|
|
4
|
+
export interface ParseCreditFacadeOperationProps {
|
|
5
|
+
sdk: OnchainSDK;
|
|
6
|
+
/** Resolved credit facade contract for the transaction target. */
|
|
7
|
+
facade: CreditFacadeV310Contract;
|
|
8
|
+
calldata: Hex;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Decodes a credit-facade entry-point call into the matching
|
|
12
|
+
* {@link OuterFacadeOperation}.
|
|
13
|
+
*
|
|
14
|
+
* Metadata is partial: `txHash` is `zeroHash` and `timestamp` is `0` because
|
|
15
|
+
* those are only known once the transaction is mined. `creditAccount` is
|
|
16
|
+
* `zeroAddress` for `openCreditAccount` (the address is assigned on-chain).
|
|
17
|
+
*/
|
|
18
|
+
export declare function parseCreditFacadeOperation(props: ParseCreditFacadeOperationProps): OuterFacadeOperation;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Hex } from "viem";
|
|
2
|
+
import type { OnchainSDK, PoolV310Contract } from "../../sdk/index.js";
|
|
3
|
+
import type { PoolOperation } from "./types.js";
|
|
4
|
+
export interface ParsePoolOperationProps {
|
|
5
|
+
sdk: OnchainSDK;
|
|
6
|
+
/** Resolved pool contract for the transaction target. */
|
|
7
|
+
pool: PoolV310Contract;
|
|
8
|
+
calldata: Hex;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Decodes ERC4626 `deposit`/`depositWithReferral`/`redeem` calldata on a
|
|
12
|
+
* Gearbox pool into a {@link PoolOperation}. Any other selector throws
|
|
13
|
+
* {@link UnsupportedPoolFunctionError}.
|
|
14
|
+
*/
|
|
15
|
+
export declare function parsePoolOperation(props: ParsePoolOperationProps): PoolOperation;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Address, Hex } from "viem";
|
|
2
|
+
import { type PluginsMap } from "../../sdk/index.js";
|
|
3
|
+
import type { ParsedTransaction, SdkWithAdapters } from "./types.js";
|
|
4
|
+
export interface ParseTransactionInput<P extends PluginsMap = PluginsMap> {
|
|
5
|
+
/**
|
|
6
|
+
* Already-attached SDK; chain, RPC and block are baked in at attach time.
|
|
7
|
+
* Must be created with the adapters plugin (enforced at compile time) so
|
|
8
|
+
* adapter contracts resolve during multicall classification.
|
|
9
|
+
*/
|
|
10
|
+
sdk: SdkWithAdapters<P>;
|
|
11
|
+
to: Address;
|
|
12
|
+
calldata: Hex;
|
|
13
|
+
/** Transaction sender, contextual only. */
|
|
14
|
+
sender: Address;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Decodes raw transaction calldata into a {@link ParsedTransaction}.
|
|
18
|
+
*
|
|
19
|
+
* Routes by the resolved contract at `to`: a pool yields a deposit/redeem
|
|
20
|
+
* operation, a credit facade yields one facade operation. Anything else throws
|
|
21
|
+
* {@link UnsupportedTargetError}.
|
|
22
|
+
*/
|
|
23
|
+
export declare function parseTransaction<P extends PluginsMap>(input: ParseTransactionInput<P>): ParsedTransaction;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { Address } from "viem";
|
|
2
|
+
import type { OuterFacadeOperation } from "../../history/index.js";
|
|
3
|
+
import type { AdaptersPlugin, TokenTransfer } from "../../plugins/adapters/index.js";
|
|
4
|
+
import type { OnchainSDK, PluginsMap } from "../../sdk/index.js";
|
|
5
|
+
/**
|
|
6
|
+
* True when the plugin map `P` contains the {@link AdaptersPlugin} under any
|
|
7
|
+
* key. Matched nominally (the plugin's private fields make it non-structural),
|
|
8
|
+
* so unrelated plugins never satisfy it.
|
|
9
|
+
*/
|
|
10
|
+
export type HasAdaptersPlugin<P extends PluginsMap> = Extract<P[keyof P], AdaptersPlugin> extends never ? false : true;
|
|
11
|
+
/**
|
|
12
|
+
* Compile-time guard for the adapters plugin. Resolves to a no-op (`unknown`)
|
|
13
|
+
* when `P` includes the {@link AdaptersPlugin}, otherwise to an error-shaped
|
|
14
|
+
* type that makes the surrounding call fail to type-check.
|
|
15
|
+
*
|
|
16
|
+
* Intended to be intersected with a function argument so callers must pass an
|
|
17
|
+
* SDK whose adapter contracts are registered (required for multicall
|
|
18
|
+
* classification).
|
|
19
|
+
*/
|
|
20
|
+
export type RequireAdaptersPlugin<P extends PluginsMap> = HasAdaptersPlugin<P> extends true ? unknown : {
|
|
21
|
+
"OnchainSDK must be created with the AdaptersPlugin": never;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* {@link OnchainSDK} whose plugin map is guaranteed at compile time to include
|
|
25
|
+
* the {@link AdaptersPlugin}.
|
|
26
|
+
*/
|
|
27
|
+
export type SdkWithAdapters<P extends PluginsMap = PluginsMap> = OnchainSDK<P> & RequireAdaptersPlugin<P>;
|
|
28
|
+
/**
|
|
29
|
+
* ERC4626 `deposit` into a Gearbox pool.
|
|
30
|
+
* Token metadata (symbol/decimals) is intentionally omitted: consumers resolve
|
|
31
|
+
* it from `sdk.tokensMeta` using the token addresses below.
|
|
32
|
+
*/
|
|
33
|
+
export interface PoolDepositOperation {
|
|
34
|
+
operation: "Deposit";
|
|
35
|
+
pool: Address;
|
|
36
|
+
receiver: Address;
|
|
37
|
+
/** Underlying assets supplied to the pool. */
|
|
38
|
+
assets: bigint;
|
|
39
|
+
underlying: Address;
|
|
40
|
+
/** Referral code, present only for `depositWithReferral` calls. */
|
|
41
|
+
referralCode?: bigint;
|
|
42
|
+
/**
|
|
43
|
+
* ERC-20 transfers involving the wallet, recovered by simulating the call.
|
|
44
|
+
* Empty for the calldata-only parse; populated by the simulation stage.
|
|
45
|
+
*/
|
|
46
|
+
transfers: TokenTransfer[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* ERC4626 `redeem` from a Gearbox pool.
|
|
50
|
+
* Token metadata (symbol/decimals) is intentionally omitted: consumers resolve
|
|
51
|
+
* it from `sdk.tokensMeta` using the token addresses below.
|
|
52
|
+
*/
|
|
53
|
+
export interface PoolRedeemOperation {
|
|
54
|
+
operation: "Redeem";
|
|
55
|
+
pool: Address;
|
|
56
|
+
receiver: Address;
|
|
57
|
+
owner: Address;
|
|
58
|
+
/** Pool shares (diesel) burned. */
|
|
59
|
+
shares: bigint;
|
|
60
|
+
underlying: Address;
|
|
61
|
+
/**
|
|
62
|
+
* ERC-20 transfers involving the wallet, recovered by simulating the call.
|
|
63
|
+
* Empty for the calldata-only parse; populated by the simulation stage.
|
|
64
|
+
*/
|
|
65
|
+
transfers: TokenTransfer[];
|
|
66
|
+
}
|
|
67
|
+
export type PoolOperation = PoolDepositOperation | PoolRedeemOperation;
|
|
68
|
+
/**
|
|
69
|
+
* Narrows a {@link ParsedTransaction} to a {@link PoolOperation} (deposit or
|
|
70
|
+
* redeem). Used by the UI to decide whether a custom view exists for the parsed
|
|
71
|
+
* result; everything else falls back to the raw JSON view.
|
|
72
|
+
*/
|
|
73
|
+
export declare function isPoolOperation(tx: ParsedTransaction): tx is PoolOperation;
|
|
74
|
+
/**
|
|
75
|
+
* Result of decoding a single raw transaction calldata: either a pool
|
|
76
|
+
* deposit/redeem or one of the credit-facade operations from `sdk/history`.
|
|
77
|
+
*/
|
|
78
|
+
export type ParsedTransaction = PoolOperation | OuterFacadeOperation;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type Address, type ContractFunctionParameters } from "viem";
|
|
2
|
+
import { type MulticallCallResult, Prerequisite } from "./Prerequisite.js";
|
|
3
|
+
import type { PrerequisiteDetail, PrerequisiteResult } from "./types.js";
|
|
4
|
+
export interface AllowancePrerequisiteProps {
|
|
5
|
+
token: Address;
|
|
6
|
+
owner: Address;
|
|
7
|
+
spender: Address;
|
|
8
|
+
required: bigint;
|
|
9
|
+
title?: string;
|
|
10
|
+
id?: string;
|
|
11
|
+
}
|
|
12
|
+
/** Checks that `owner` granted `spender` an ERC-20 allowance >= `required`. */
|
|
13
|
+
export declare class AllowancePrerequisite extends Prerequisite<"allowance"> {
|
|
14
|
+
private readonly _id;
|
|
15
|
+
private readonly _title;
|
|
16
|
+
private readonly _detail;
|
|
17
|
+
constructor(props: AllowancePrerequisiteProps);
|
|
18
|
+
get id(): string;
|
|
19
|
+
get kind(): "allowance";
|
|
20
|
+
get title(): string;
|
|
21
|
+
get detail(): PrerequisiteDetail<"allowance">;
|
|
22
|
+
calls(): ContractFunctionParameters[];
|
|
23
|
+
resolve(slice: MulticallCallResult[]): PrerequisiteResult<"allowance">;
|
|
24
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type Address, type ContractFunctionParameters } from "viem";
|
|
2
|
+
import { type MulticallCallResult, Prerequisite } from "./Prerequisite.js";
|
|
3
|
+
import type { PrerequisiteDetail, PrerequisiteResult } from "./types.js";
|
|
4
|
+
export interface BalancePrerequisiteProps {
|
|
5
|
+
token: Address;
|
|
6
|
+
owner: Address;
|
|
7
|
+
required: bigint;
|
|
8
|
+
title?: string;
|
|
9
|
+
id?: string;
|
|
10
|
+
}
|
|
11
|
+
/** Checks that `owner` holds an ERC-20 balance >= `required`. */
|
|
12
|
+
export declare class BalancePrerequisite extends Prerequisite<"balance"> {
|
|
13
|
+
private readonly _id;
|
|
14
|
+
private readonly _title;
|
|
15
|
+
private readonly _detail;
|
|
16
|
+
constructor(props: BalancePrerequisiteProps);
|
|
17
|
+
get id(): string;
|
|
18
|
+
get kind(): "balance";
|
|
19
|
+
get title(): string;
|
|
20
|
+
get detail(): PrerequisiteDetail<"balance">;
|
|
21
|
+
calls(): ContractFunctionParameters[];
|
|
22
|
+
resolve(slice: MulticallCallResult[]): PrerequisiteResult<"balance">;
|
|
23
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type ContractFunctionParameters } from "viem";
|
|
2
|
+
import type { PrerequisiteContext, PrerequisiteDetail, PrerequisiteError, PrerequisiteKind, PrerequisiteResult } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* One entry of a viem `multicall({ allowFailure: true })` response: either a
|
|
5
|
+
* decoded `result` or the `error` that the call reverted with.
|
|
6
|
+
*/
|
|
7
|
+
export type MulticallCallResult = {
|
|
8
|
+
status: "success";
|
|
9
|
+
result: unknown;
|
|
10
|
+
error?: undefined;
|
|
11
|
+
} | {
|
|
12
|
+
status: "failure";
|
|
13
|
+
result?: undefined;
|
|
14
|
+
error: Error;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Decodes an unknown error into a {@link PrerequisiteError} with a
|
|
18
|
+
* human-readable revert reason. Mirrors the SDK's `extractCallError`: walk the
|
|
19
|
+
* viem error chain for a {@link ContractFunctionRevertedError} and use its
|
|
20
|
+
* `errorName`, otherwise fall back to the error's short message / name.
|
|
21
|
+
*/
|
|
22
|
+
export declare function toPrerequisiteError(cause: unknown): PrerequisiteError;
|
|
23
|
+
/**
|
|
24
|
+
* A single verifiable prerequisite for a transaction. Subclasses describe the
|
|
25
|
+
* on-chain reads they need ({@link calls}) and how to turn the multicall slice
|
|
26
|
+
* into a {@link PrerequisiteResult} ({@link resolve}).
|
|
27
|
+
*
|
|
28
|
+
* Identity (`id`, `kind`, `title`) and build-time `detail` are exposed as
|
|
29
|
+
* read-only accessors; subclasses back them with private fields. The shared
|
|
30
|
+
* {@link satisfiedResult}/{@link errorResult} helpers are `protected` so each
|
|
31
|
+
* subclass builds results consistently.
|
|
32
|
+
*
|
|
33
|
+
* The same instance can be verified standalone via {@link verify} or batched
|
|
34
|
+
* together with others by `verifyPrerequisites`.
|
|
35
|
+
*/
|
|
36
|
+
export declare abstract class Prerequisite<K extends PrerequisiteKind> {
|
|
37
|
+
/** Stable identifier, used as a React key and for deduplication. */
|
|
38
|
+
abstract get id(): string;
|
|
39
|
+
/** Discriminant tying this check to its detail payload. */
|
|
40
|
+
abstract get kind(): K;
|
|
41
|
+
/** Human-readable label shown in the UI. */
|
|
42
|
+
abstract get title(): string;
|
|
43
|
+
/** Inputs known before reading the chain (no `actual` yet). */
|
|
44
|
+
abstract get detail(): PrerequisiteDetail<K>;
|
|
45
|
+
/** Contract reads this check needs (usually one). */
|
|
46
|
+
abstract calls(ctx: PrerequisiteContext): ContractFunctionParameters[];
|
|
47
|
+
/** Maps this check's slice of the multicall response into a result. */
|
|
48
|
+
abstract resolve(slice: MulticallCallResult[]): PrerequisiteResult<K>;
|
|
49
|
+
/**
|
|
50
|
+
* Verifies this prerequisite on its own using an `allowFailure` multicall.
|
|
51
|
+
* Prefer `verifyPrerequisites` to batch several checks into one round-trip.
|
|
52
|
+
*/
|
|
53
|
+
verify(ctx: PrerequisiteContext): Promise<PrerequisiteResult<K>>;
|
|
54
|
+
/** Builds a successful result; `detail` carries the on-chain `actual`. */
|
|
55
|
+
protected satisfiedResult(satisfied: boolean, detail: PrerequisiteDetail<K>): PrerequisiteResult<K>;
|
|
56
|
+
/** Builds a failed result from a decoded read error. */
|
|
57
|
+
protected errorResult(error: PrerequisiteError): PrerequisiteResult<K>;
|
|
58
|
+
}
|
|
59
|
+
/** Any prerequisite regardless of its kind, used for heterogeneous lists. */
|
|
60
|
+
export type AnyPrerequisite = Prerequisite<PrerequisiteKind>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ParsedTransaction } from "../parse/index.js";
|
|
2
|
+
import type { AnyPrerequisite } from "./Prerequisite.js";
|
|
3
|
+
import type { PrerequisiteContext } from "./types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Derives the on-chain prerequisites for a parsed transaction: the conditions
|
|
6
|
+
* that must hold for the call not to revert and that we can verify with the
|
|
7
|
+
* SDK (token approvals, wallet balances).
|
|
8
|
+
*
|
|
9
|
+
* Only *sender-actionable* prerequisites belong here: conditions the LP
|
|
10
|
+
* provider or borrower can fix themselves before retrying (e.g. approve a
|
|
11
|
+
* token, top up a balance). Non-actionable protocol/admin state (pool pause,
|
|
12
|
+
* available pool liquidity, health factor, liquidatability, degen NFT gating,
|
|
13
|
+
* bot permissions) is intentionally out of scope, since the user cannot
|
|
14
|
+
* resolve it. New {@link AnyPrerequisite} subclasses must follow the same rule.
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildPrerequisites(tx: ParsedTransaction, ctx: PrerequisiteContext): AnyPrerequisite[];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AnyPrerequisite } from "./Prerequisite.js";
|
|
2
|
+
import type { AnyPrerequisiteResult, PrerequisiteContext } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Verifies all prerequisites in a single resilient multicall.
|
|
5
|
+
*
|
|
6
|
+
* Every prereq contributes its reads to one `multicall({ allowFailure: true })`
|
|
7
|
+
* batch, then resolves its own slice of the response. A read that reverts
|
|
8
|
+
* isolates to that prerequisite (an `error` result) without affecting the
|
|
9
|
+
* others; if the whole round-trip fails (RPC/network), every prerequisite
|
|
10
|
+
* resolves to an `error` carrying that reason.
|
|
11
|
+
*/
|
|
12
|
+
export declare function verifyPrerequisites(prereqs: AnyPrerequisite[], ctx: PrerequisiteContext): Promise<AnyPrerequisiteResult[]>;
|