@w3lib/evm-batch-call 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/README.md +206 -1
- package/dist/dividends.d.ts +135 -0
- package/dist/dividends.d.ts.map +1 -0
- package/dist/dividends.js +253 -0
- package/dist/dividends.js.map +1 -0
- package/dist/history.d.ts +154 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +247 -0
- package/dist/history.js.map +1 -0
- package/dist/historySources.d.ts +32 -0
- package/dist/historySources.d.ts.map +1 -0
- package/dist/historySources.js +319 -0
- package/dist/historySources.js.map +1 -0
- package/dist/liquidity/v3.d.ts +2 -0
- package/dist/liquidity/v3.d.ts.map +1 -1
- package/dist/liquidity/v3.js +1 -1
- package/dist/liquidity/v3.js.map +1 -1
- package/dist/liquidity/v4.d.ts +21 -0
- package/dist/liquidity/v4.d.ts.map +1 -1
- package/dist/liquidity/v4.js +4 -3
- package/dist/liquidity/v4.js.map +1 -1
- package/dist/lp.d.ts +8 -0
- package/dist/lp.d.ts.map +1 -1
- package/dist/lp.js +17 -1
- package/dist/lp.js.map +1 -1
- package/dist/lpV4.d.ts +4 -0
- package/dist/lpV4.d.ts.map +1 -1
- package/dist/lpV4.js +27 -3
- package/dist/lpV4.js.map +1 -1
- package/dist/permit.d.ts +137 -0
- package/dist/permit.d.ts.map +1 -0
- package/dist/permit.js +355 -0
- package/dist/permit.js.map +1 -0
- package/dist/portfolio.d.ts +2 -0
- package/dist/portfolio.d.ts.map +1 -1
- package/dist/portfolio.js +9 -4
- package/dist/portfolio.js.map +1 -1
- package/dist/rewards/farms.d.ts +26 -0
- package/dist/rewards/farms.d.ts.map +1 -0
- package/dist/rewards/farms.js +210 -0
- package/dist/rewards/farms.js.map +1 -0
- package/dist/rewards/index.d.ts +42 -0
- package/dist/rewards/index.d.ts.map +1 -0
- package/dist/rewards/index.js +382 -0
- package/dist/rewards/index.js.map +1 -0
- package/dist/rewards/types.d.ts +170 -0
- package/dist/rewards/types.d.ts.map +1 -0
- package/dist/rewards/types.js +2 -0
- package/dist/rewards/types.js.map +1 -0
- package/dist/simulate.d.ts +186 -0
- package/dist/simulate.d.ts.map +1 -0
- package/dist/simulate.js +559 -0
- package/dist/simulate.js.map +1 -0
- package/dist/simulateDecode.d.ts +33 -0
- package/dist/simulateDecode.d.ts.map +1 -0
- package/dist/simulateDecode.js +321 -0
- package/dist/simulateDecode.js.map +1 -0
- package/dist/smartAccount/account.d.ts +31 -0
- package/dist/smartAccount/account.d.ts.map +1 -0
- package/dist/smartAccount/account.js +33 -0
- package/dist/smartAccount/account.js.map +1 -0
- package/dist/smartAccount/clients.d.ts +77 -0
- package/dist/smartAccount/clients.d.ts.map +1 -0
- package/dist/smartAccount/clients.js +122 -0
- package/dist/smartAccount/clients.js.map +1 -0
- package/dist/smartAccount/eip5792.d.ts +77 -0
- package/dist/smartAccount/eip5792.d.ts.map +1 -0
- package/dist/smartAccount/eip5792.js +152 -0
- package/dist/smartAccount/eip5792.js.map +1 -0
- package/dist/smartAccount/send.d.ts +40 -0
- package/dist/smartAccount/send.d.ts.map +1 -0
- package/dist/smartAccount/send.js +271 -0
- package/dist/smartAccount/send.js.map +1 -0
- package/dist/smartAccount/userOp.d.ts +91 -0
- package/dist/smartAccount/userOp.d.ts.map +1 -0
- package/dist/smartAccount/userOp.js +124 -0
- package/dist/smartAccount/userOp.js.map +1 -0
- package/dist/subpaths/dividends.d.ts +28 -0
- package/dist/subpaths/dividends.d.ts.map +1 -0
- package/dist/subpaths/dividends.js +29 -0
- package/dist/subpaths/dividends.js.map +1 -0
- package/dist/subpaths/history.d.ts +22 -0
- package/dist/subpaths/history.d.ts.map +1 -0
- package/dist/subpaths/history.js +23 -0
- package/dist/subpaths/history.js.map +1 -0
- package/dist/subpaths/permit.d.ts +14 -0
- package/dist/subpaths/permit.d.ts.map +1 -0
- package/dist/subpaths/permit.js +14 -0
- package/dist/subpaths/permit.js.map +1 -0
- package/dist/subpaths/price.js +2 -2
- package/dist/subpaths/price.js.map +1 -1
- package/dist/subpaths/rewards.d.ts +27 -0
- package/dist/subpaths/rewards.d.ts.map +1 -0
- package/dist/subpaths/rewards.js +25 -0
- package/dist/subpaths/rewards.js.map +1 -0
- package/dist/subpaths/simulate.d.ts +25 -0
- package/dist/subpaths/simulate.d.ts.map +1 -0
- package/dist/subpaths/simulate.js +28 -0
- package/dist/subpaths/simulate.js.map +1 -0
- package/dist/subpaths/smart-account.d.ts +24 -0
- package/dist/subpaths/smart-account.d.ts.map +1 -0
- package/dist/subpaths/smart-account.js +24 -0
- package/dist/subpaths/smart-account.js.map +1 -0
- package/dist/swap.d.ts +45 -5
- package/dist/swap.d.ts.map +1 -1
- package/dist/swap.js +108 -12
- package/dist/swap.js.map +1 -1
- package/dist/write/batch.d.ts +34 -2
- package/dist/write/batch.d.ts.map +1 -1
- package/dist/write/batch.js +22 -3
- package/dist/write/batch.js.map +1 -1
- package/dist/write/collect.d.ts +9 -0
- package/dist/write/collect.d.ts.map +1 -1
- package/dist/write/collect.js +41 -1
- package/dist/write/collect.js.map +1 -1
- package/dist/write/send.d.ts +4 -0
- package/dist/write/send.d.ts.map +1 -1
- package/dist/write/send.js.map +1 -1
- package/dist/write/signer.d.ts +5 -1
- package/dist/write/signer.d.ts.map +1 -1
- package/dist/write/signer.js.map +1 -1
- package/dist/write/transfer.d.ts +5 -3
- package/dist/write/transfer.d.ts.map +1 -1
- package/dist/write/transfer.js +12 -6
- package/dist/write/transfer.js.map +1 -1
- package/package.json +35 -1
- package/src/dividends.ts +360 -0
- package/src/history.ts +367 -0
- package/src/historySources.ts +360 -0
- package/src/liquidity/v3.ts +1 -1
- package/src/liquidity/v4.ts +4 -3
- package/src/lp.ts +18 -1
- package/src/lpV4.ts +32 -2
- package/src/permit.ts +457 -0
- package/src/portfolio.ts +11 -4
- package/src/rewards/farms.ts +229 -0
- package/src/rewards/index.ts +431 -0
- package/src/rewards/types.ts +179 -0
- package/src/simulate.ts +727 -0
- package/src/simulateDecode.ts +352 -0
- package/src/smartAccount/account.ts +63 -0
- package/src/smartAccount/clients.ts +180 -0
- package/src/smartAccount/eip5792.ts +187 -0
- package/src/smartAccount/send.ts +341 -0
- package/src/smartAccount/userOp.ts +180 -0
- package/src/subpaths/dividends.ts +47 -0
- package/src/subpaths/history.ts +41 -0
- package/src/subpaths/permit.ts +39 -0
- package/src/subpaths/price.ts +2 -2
- package/src/subpaths/rewards.ts +46 -0
- package/src/subpaths/simulate.ts +51 -0
- package/src/subpaths/smart-account.ts +40 -0
- package/src/swap.ts +139 -18
- package/src/write/batch.ts +44 -5
- package/src/write/collect.ts +60 -1
- package/src/write/send.ts +4 -0
- package/src/write/signer.ts +5 -1
- package/src/write/transfer.ts +17 -10
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { AbiCoder, Interface, TypedDataEncoder, concat, getAddress, getBytes, keccak256, toBeHex, zeroPadValue, type Authorization } from 'ethers'
|
|
2
|
+
|
|
3
|
+
/** ERC-4337 EntryPoint 的两个版本,各主流链上地址相同 */
|
|
4
|
+
export const ENTRY_POINT_V07 = '0x0000000071727De22E5E9d8BAf0edAc6f37da032'
|
|
5
|
+
export const ENTRY_POINT_V08 = '0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108'
|
|
6
|
+
|
|
7
|
+
export type EntryPointVersion = '0.7' | '0.8'
|
|
8
|
+
|
|
9
|
+
export function entryPointAddress(version: EntryPointVersion): string {
|
|
10
|
+
return version === '0.8' ? ENTRY_POINT_V08 : ENTRY_POINT_V07
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** EntryPoint v0.8 把 initCode 以 0x7702 开头(至少 20 字节)的 UserOperation 当作 EIP-7702 账户 */
|
|
14
|
+
export const EIP7702_MARKER = '0x7702000000000000000000000000000000000000'
|
|
15
|
+
|
|
16
|
+
/** UserOperation(bundler JSON-RPC 的“拆开”格式,数值用 bigint) */
|
|
17
|
+
export interface UserOperation {
|
|
18
|
+
sender: string
|
|
19
|
+
nonce: bigint
|
|
20
|
+
/** 账户还没部署时创建它的工厂 + calldata;EIP-7702 账户用 EIP7702_MARKER 作为 factory */
|
|
21
|
+
factory?: string
|
|
22
|
+
factoryData?: string
|
|
23
|
+
callData: string
|
|
24
|
+
callGasLimit: bigint
|
|
25
|
+
verificationGasLimit: bigint
|
|
26
|
+
preVerificationGas: bigint
|
|
27
|
+
maxFeePerGas: bigint
|
|
28
|
+
maxPriorityFeePerGas: bigint
|
|
29
|
+
paymaster?: string
|
|
30
|
+
paymasterVerificationGasLimit?: bigint
|
|
31
|
+
paymasterPostOpGasLimit?: bigint
|
|
32
|
+
paymasterData?: string
|
|
33
|
+
signature: string
|
|
34
|
+
/** EIP-7702 授权(账户还没委托时随 UserOperation 一起交给 bundler) */
|
|
35
|
+
eip7702Auth?: Authorization
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** 打包后的 UserOperation(EntryPoint.handleOps 的参数) */
|
|
39
|
+
export interface PackedUserOperation {
|
|
40
|
+
sender: string
|
|
41
|
+
nonce: bigint
|
|
42
|
+
initCode: string
|
|
43
|
+
callData: string
|
|
44
|
+
accountGasLimits: string
|
|
45
|
+
preVerificationGas: bigint
|
|
46
|
+
gasFees: string
|
|
47
|
+
paymasterAndData: string
|
|
48
|
+
signature: string
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const u128 = (value: bigint) => zeroPadValue(toBeHex(value), 16)
|
|
52
|
+
|
|
53
|
+
export function initCodeOf(op: Pick<UserOperation, 'factory' | 'factoryData'>): string {
|
|
54
|
+
return op.factory ? concat([op.factory, op.factoryData ?? '0x']) : '0x'
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function paymasterAndDataOf(op: UserOperation): string {
|
|
58
|
+
if (!op.paymaster) {
|
|
59
|
+
return '0x'
|
|
60
|
+
}
|
|
61
|
+
return concat([op.paymaster, u128(op.paymasterVerificationGasLimit ?? 0n), u128(op.paymasterPostOpGasLimit ?? 0n), op.paymasterData ?? '0x'])
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function packUserOp(op: UserOperation): PackedUserOperation {
|
|
65
|
+
return {
|
|
66
|
+
sender: getAddress(op.sender),
|
|
67
|
+
nonce: op.nonce,
|
|
68
|
+
initCode: initCodeOf(op),
|
|
69
|
+
callData: op.callData,
|
|
70
|
+
accountGasLimits: concat([u128(op.verificationGasLimit), u128(op.callGasLimit)]),
|
|
71
|
+
preVerificationGas: op.preVerificationGas,
|
|
72
|
+
gasFees: concat([u128(op.maxPriorityFeePerGas), u128(op.maxFeePerGas)]),
|
|
73
|
+
paymasterAndData: paymasterAndDataOf(op),
|
|
74
|
+
signature: op.signature,
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** v0.8 的 EIP-712 类型(userOpHash 就是它的摘要,所以钱包可以直接 signTypedData 签) */
|
|
79
|
+
export const USER_OP_TYPES = {
|
|
80
|
+
PackedUserOperation: [
|
|
81
|
+
{ name: 'sender', type: 'address' },
|
|
82
|
+
{ name: 'nonce', type: 'uint256' },
|
|
83
|
+
{ name: 'initCode', type: 'bytes' },
|
|
84
|
+
{ name: 'callData', type: 'bytes' },
|
|
85
|
+
{ name: 'accountGasLimits', type: 'bytes32' },
|
|
86
|
+
{ name: 'preVerificationGas', type: 'uint256' },
|
|
87
|
+
{ name: 'gasFees', type: 'bytes32' },
|
|
88
|
+
{ name: 'paymasterAndData', type: 'bytes' },
|
|
89
|
+
],
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* v0.8 的 EIP-712 数据。EIP-7702 账户(initCode 以 0x7702 开头):EntryPoint 算哈希时把 initCode 换成
|
|
94
|
+
* “账户当前委托的合约地址 ‖ initCode[20:]”,所以要传 delegate(账户将要委托 / 已委托的合约)
|
|
95
|
+
*/
|
|
96
|
+
export function userOpTypedData(op: UserOperation, entryPoint: string, chainId: number, delegate?: string) {
|
|
97
|
+
const packed = packUserOp(op)
|
|
98
|
+
let initCode = packed.initCode
|
|
99
|
+
if (initCode.toLowerCase().startsWith('0x7702') && getBytes(initCode).length >= 20) {
|
|
100
|
+
if (!delegate) {
|
|
101
|
+
throw new Error('delegate is required to hash an EIP-7702 UserOperation')
|
|
102
|
+
}
|
|
103
|
+
initCode = concat([getAddress(delegate), `0x${initCode.slice(2 + 40)}`])
|
|
104
|
+
}
|
|
105
|
+
const { signature: _signature, ...message } = packed
|
|
106
|
+
return {
|
|
107
|
+
domain: { name: 'ERC4337', version: '1', chainId, verifyingContract: getAddress(entryPoint) },
|
|
108
|
+
types: USER_OP_TYPES,
|
|
109
|
+
message: { ...message, initCode },
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** UserOperation 哈希(与 EntryPoint.getUserOpHash 一致) */
|
|
114
|
+
export function getUserOpHash(op: UserOperation, entryPoint: string, chainId: number, version: EntryPointVersion, delegate?: string): string {
|
|
115
|
+
if (version === '0.8') {
|
|
116
|
+
const { domain, types, message } = userOpTypedData(op, entryPoint, chainId, delegate)
|
|
117
|
+
return TypedDataEncoder.hash(domain, types, message)
|
|
118
|
+
}
|
|
119
|
+
const p = packUserOp(op)
|
|
120
|
+
const coder = AbiCoder.defaultAbiCoder()
|
|
121
|
+
const inner = keccak256(
|
|
122
|
+
coder.encode(
|
|
123
|
+
['address', 'uint256', 'bytes32', 'bytes32', 'bytes32', 'uint256', 'bytes32', 'bytes32'],
|
|
124
|
+
[p.sender, p.nonce, keccak256(p.initCode), keccak256(p.callData), p.accountGasLimits, p.preVerificationGas, p.gasFees, keccak256(p.paymasterAndData)],
|
|
125
|
+
),
|
|
126
|
+
)
|
|
127
|
+
return keccak256(coder.encode(['bytes32', 'address', 'uint256'], [inner, getAddress(entryPoint), chainId]))
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** JSON-RPC 数值:0x 十六进制、没有前导零 */
|
|
131
|
+
export const quantity = (v: bigint | number): string => `0x${v.toString(16)}`
|
|
132
|
+
|
|
133
|
+
/** bundler JSON-RPC 的 UserOperation(数值为 0x 十六进制) */
|
|
134
|
+
export function userOpToRpc(op: UserOperation): Record<string, unknown> {
|
|
135
|
+
const q = quantity
|
|
136
|
+
const rpc: Record<string, unknown> = { sender: getAddress(op.sender), nonce: q(op.nonce), callData: op.callData }
|
|
137
|
+
if (op.factory) {
|
|
138
|
+
rpc.factory = op.factory
|
|
139
|
+
rpc.factoryData = op.factoryData ?? '0x'
|
|
140
|
+
}
|
|
141
|
+
Object.assign(rpc, {
|
|
142
|
+
callGasLimit: q(op.callGasLimit),
|
|
143
|
+
verificationGasLimit: q(op.verificationGasLimit),
|
|
144
|
+
preVerificationGas: q(op.preVerificationGas),
|
|
145
|
+
maxFeePerGas: q(op.maxFeePerGas),
|
|
146
|
+
maxPriorityFeePerGas: q(op.maxPriorityFeePerGas),
|
|
147
|
+
})
|
|
148
|
+
if (op.paymaster) {
|
|
149
|
+
Object.assign(rpc, {
|
|
150
|
+
paymaster: op.paymaster,
|
|
151
|
+
paymasterVerificationGasLimit: q(op.paymasterVerificationGasLimit ?? 0n),
|
|
152
|
+
paymasterPostOpGasLimit: q(op.paymasterPostOpGasLimit ?? 0n),
|
|
153
|
+
paymasterData: op.paymasterData ?? '0x',
|
|
154
|
+
})
|
|
155
|
+
}
|
|
156
|
+
rpc.signature = op.signature
|
|
157
|
+
if (op.eip7702Auth) {
|
|
158
|
+
const a = op.eip7702Auth
|
|
159
|
+
rpc.eip7702Auth = { chainId: q(BigInt(a.chainId)), address: a.address, nonce: q(BigInt(a.nonce)), yParity: a.signature.yParity === 0 ? '0x0' : '0x1', r: a.signature.r, s: a.signature.s }
|
|
160
|
+
}
|
|
161
|
+
return rpc
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** 估算 gas 时用的占位签名(65 字节、格式合法的 ECDSA 签名,账户校验时不会因为长度 / 格式直接 revert) */
|
|
165
|
+
export const DUMMY_SIGNATURE = `0x${'f'.repeat(31)}0${'0'.repeat(32)}7${'a'.repeat(63)}1c`
|
|
166
|
+
|
|
167
|
+
export const entryPointInterface = new Interface([
|
|
168
|
+
'function handleOps((address sender, uint256 nonce, bytes initCode, bytes callData, bytes32 accountGasLimits, uint256 preVerificationGas, bytes32 gasFees, bytes paymasterAndData, bytes signature)[] ops, address beneficiary)',
|
|
169
|
+
'function getNonce(address sender, uint192 key) view returns (uint256)',
|
|
170
|
+
'function getUserOpHash((address sender, uint256 nonce, bytes initCode, bytes callData, bytes32 accountGasLimits, uint256 preVerificationGas, bytes32 gasFees, bytes paymasterAndData, bytes signature) userOp) view returns (bytes32)',
|
|
171
|
+
'error FailedOp(uint256 opIndex, string reason)',
|
|
172
|
+
'error FailedOpWithRevert(uint256 opIndex, string reason, bytes inner)',
|
|
173
|
+
'event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed)',
|
|
174
|
+
'event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason)',
|
|
175
|
+
])
|
|
176
|
+
|
|
177
|
+
/** 十六进制数值 → bigint(bundler 返回的字段) */
|
|
178
|
+
export function hexToBigInt(value: unknown): bigint {
|
|
179
|
+
return value === undefined || value === null ? 0n : BigInt(value as string)
|
|
180
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flap 分红(子路径 `@w3lib/evm-batch-call/dividends`):查持有人在 Flap(flap.sh,BNB Chain 发币平台)税收代币上累计的分红
|
|
3
|
+
* (可领取 / 已领取、分红资产、美元价值),批量领取(可用 7702 / 4337 / 5792 合成一笔原子交易)。
|
|
4
|
+
* 不放在主入口,不用时打包不会带上这部分代码;发送和模拟的代码按需加载。只支持 BSC,合约形态和核实范围见 README「Flap 分红」。
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { getDividends, claimDividends } from '@w3lib/evm-batch-call/dividends'
|
|
8
|
+
*
|
|
9
|
+
* const { items } = await getDividends(user, { chainId: 56, discover: true }) // 或 tokens: [flapToken]
|
|
10
|
+
* await claimDividends(provider, key, items, { mode: '7702', simulate: true })
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
import { dividends, type DividendsOptions, type DividendsResult } from '../dividends.js'
|
|
14
|
+
import { resolve, type ShortcutProviderOptions } from '../shortcuts.js'
|
|
15
|
+
|
|
16
|
+
export {
|
|
17
|
+
FLAP_DIVIDEND_CHAINS,
|
|
18
|
+
FLAP_TOKEN_SUFFIXES,
|
|
19
|
+
buildClaimDividends,
|
|
20
|
+
claimDividends,
|
|
21
|
+
dividends,
|
|
22
|
+
scanDividendTokens,
|
|
23
|
+
type ClaimDividendResult,
|
|
24
|
+
type ClaimDividendTx,
|
|
25
|
+
type ClaimDividendsOptions,
|
|
26
|
+
type DividendItem,
|
|
27
|
+
type DividendScanOptions,
|
|
28
|
+
type DividendUnsupported,
|
|
29
|
+
type DividendsOptions,
|
|
30
|
+
type DividendsResult,
|
|
31
|
+
} from '../dividends.js'
|
|
32
|
+
|
|
33
|
+
export interface GetDividendsOptions extends DividendsOptions, ShortcutProviderOptions {}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* 查持有人在 Flap 代币上的分红,节点参数与 getBalances 相同(chainId 只能是 56)。
|
|
37
|
+
* tokens 给定要查的代币;discover 从收到过的 Transfer 事件里发现(卖光的代币上之前累计的分红也能领)。
|
|
38
|
+
*
|
|
39
|
+
* ```ts
|
|
40
|
+
* const { items, unsupported } = await getDividends(user, { chainId: 56, tokens: [flapToken] })
|
|
41
|
+
* // [{ token, symbol, balance, claimable: '88823258714382840', asset: '0x9b8E…', assetSymbol: 'FXIon', usd: null, dividendContract, … }]
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export function getDividends(owner: string, options: GetDividendsOptions = {}): Promise<DividendsResult> {
|
|
45
|
+
const { provider, own } = resolve(options, ['tokens', 'discover', 'prices', 'fetch', 'includeZero'])
|
|
46
|
+
return dividends(provider, owner, own as DividendsOptions)
|
|
47
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 交易历史(子路径 `@w3lib/evm-batch-call/history`):一个地址的转账 / 兑换 / 授权 / 流动性 / 铸造记录,带解码后的类型、资产变化和手续费。
|
|
3
|
+
* 数据来源可替换、可故障切换:Blockscout(免 Key,默认)、Etherscan v2(传 apiKey)、纯 RPC 日志、Tron 的 TronGrid。
|
|
4
|
+
* 不放在主入口,不用时打包不会带上这部分代码。
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { getHistory } from '@w3lib/evm-batch-call/history'
|
|
8
|
+
*
|
|
9
|
+
* const page = await getHistory(user, { chainId: 1, limit: 20 })
|
|
10
|
+
* const more = await getHistory(user, { chainId: 1, cursor: page.nextCursor, types: ['swap'] })
|
|
11
|
+
* await getHistory(user, { chainId: 56, source: ['etherscan', 'rpc'], apiKey })
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
import { history, type HistoryOptions, type HistoryResult } from '../history.js'
|
|
15
|
+
import { resolve, type ShortcutProviderOptions } from '../shortcuts.js'
|
|
16
|
+
|
|
17
|
+
export {
|
|
18
|
+
HistorySourceError,
|
|
19
|
+
buildActivities,
|
|
20
|
+
history,
|
|
21
|
+
type Activity,
|
|
22
|
+
type ActivityChange,
|
|
23
|
+
type ActivityType,
|
|
24
|
+
type HistoryAdapter,
|
|
25
|
+
type HistoryOptions,
|
|
26
|
+
type HistoryQuery,
|
|
27
|
+
type HistoryResult,
|
|
28
|
+
type HistorySource,
|
|
29
|
+
type RawMove,
|
|
30
|
+
type RawPage,
|
|
31
|
+
type RawTx,
|
|
32
|
+
} from '../history.js'
|
|
33
|
+
export { BLOCKSCOUT_APIS, blockscoutSource, etherscanSource, explorerSource, rpcSource, trongridSource, type RpcSourceOptions, type TrongridSourceOptions } from '../historySources.js'
|
|
34
|
+
|
|
35
|
+
export interface GetHistoryOptions extends HistoryOptions, ShortcutProviderOptions {}
|
|
36
|
+
|
|
37
|
+
/** 查一个地址的历史活动,节点参数与 getBalances 相同(只有 rpc 来源会用到节点) */
|
|
38
|
+
export function getHistory(address: string, options: GetHistoryOptions = {}): Promise<HistoryResult> {
|
|
39
|
+
const { provider, own } = resolve(options, ['source', 'apiKey', 'limit', 'cursor', 'types', 'before', 'after', 'nft', 'maxPages', 'fetch'])
|
|
40
|
+
return history(provider, address, own)
|
|
41
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 免 gas 授权(子路径 `@w3lib/evm-batch-call/permit`):EIP-2612 permit、DAI 风格 permit、Permit2(PermitSingle / PermitBatch / permitTransferFrom)。
|
|
3
|
+
* 构建 EIP-712 数据 → 用 ethers Signer 签名 → 本地验证 → 生成上链的 calldata。不放在主入口,不用时打包不会带上。
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { buildPermit, signPermit, permitCalldata } from '@w3lib/evm-batch-call/permit'
|
|
7
|
+
*
|
|
8
|
+
* const permit = await buildPermit(provider, { token: USDC, owner, spender: router, value: 100_000_000n }) // 精确额度,30 分钟有效
|
|
9
|
+
* const signed = await signPermit(signer, permit) // signer:Wallet / 浏览器钱包的 JsonRpcSigner
|
|
10
|
+
* const data = permitCalldata(signed) // token.permit(...) 的 calldata,谁都可以提交
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export {
|
|
14
|
+
DEFAULT_PERMIT_DEADLINE,
|
|
15
|
+
MAX_PERMIT_DEADLINE,
|
|
16
|
+
MAX_UINT160,
|
|
17
|
+
PERMIT2_ADDRESS,
|
|
18
|
+
assertPermitSafe,
|
|
19
|
+
buildPermit,
|
|
20
|
+
buildPermit2Batch,
|
|
21
|
+
buildPermit2Single,
|
|
22
|
+
buildPermit2Transfer,
|
|
23
|
+
detectPermit,
|
|
24
|
+
permit2Calldata,
|
|
25
|
+
permitCalldata,
|
|
26
|
+
permitTransferFromCalldata,
|
|
27
|
+
signPermit,
|
|
28
|
+
verifyPermitSignature,
|
|
29
|
+
type BuildPermitParams,
|
|
30
|
+
type Permit,
|
|
31
|
+
type Permit2AllowanceParams,
|
|
32
|
+
type Permit2BatchParams,
|
|
33
|
+
type Permit2TransferParams,
|
|
34
|
+
type PermitKind,
|
|
35
|
+
type PermitOptions,
|
|
36
|
+
type PermitSupport,
|
|
37
|
+
type SignedPermit,
|
|
38
|
+
type TypedData,
|
|
39
|
+
} from '../permit.js'
|
package/src/subpaths/price.ts
CHANGED
|
@@ -55,6 +55,6 @@ export interface GetPortfolioOptions extends PortfolioOptions, ShortcutProviderO
|
|
|
55
55
|
* ```
|
|
56
56
|
*/
|
|
57
57
|
export function getPortfolio(owner: string, options: GetPortfolioOptions): Promise<Portfolio> {
|
|
58
|
-
const { provider, own } = resolve(options, ['tokens', 'sources', 'lp', 'minUsd', 'onPriceError', 'fetch'])
|
|
59
|
-
return portfolio(provider, owner, own as PortfolioOptions)
|
|
58
|
+
const { provider, overrides, own } = resolve(options, ['tokens', 'sources', 'lp', 'minUsd', 'onPriceError', 'fetch'])
|
|
59
|
+
return portfolio(provider, owner, { ...(own as PortfolioOptions), ...(overrides.signal ? { signal: overrides.signal } : {}) })
|
|
60
60
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 一键领取手续费和挖矿奖励(子路径 `@w3lib/evm-batch-call/rewards`):V3 / V4 仓位(含 Tron 的 SunSwap V3)未领取的手续费、
|
|
3
|
+
* PancakeSwap V3 MasterChef 的 CAKE(和质押仓位的手续费)、Aerodrome / Velodrome Slipstream gauge 的奖励。
|
|
4
|
+
* 不放在主入口,不用时打包不会带上这部分代码。
|
|
5
|
+
*
|
|
6
|
+
* - getClaimable:只读,列出每个仓位能领什么(数量 + 美元价值)
|
|
7
|
+
* - buildClaimAll:合并成尽量少的交易(V3 multicall、V4 一次 modifyLiquidities、MasterChef multicall),先模拟、剔除会失败的项
|
|
8
|
+
* - claimAll:构建后签名发送;`mode: '7702' | '4337' | '5792'` 时合成一笔原子交易
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { claimAll, getClaimable } from '@w3lib/evm-batch-call/rewards'
|
|
12
|
+
*
|
|
13
|
+
* const c = await getClaimable(user, { chainId: 56, prices: true }) // c.items、c.totals、c.usd
|
|
14
|
+
* const { status, claimed } = await claimAll(multi, privateKey, { minUsd: 1 })
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
import { resolve, type ShortcutProviderOptions } from '../shortcuts.js'
|
|
18
|
+
import { claimable } from '../rewards/index.js'
|
|
19
|
+
import type { Claimable, ClaimableOptions } from '../rewards/types.js'
|
|
20
|
+
|
|
21
|
+
export { FARM_PROTOCOLS, buildClaimAll, claimAll, claimable } from '../rewards/index.js'
|
|
22
|
+
export type {
|
|
23
|
+
ClaimAllOptions,
|
|
24
|
+
ClaimAllSendOptions,
|
|
25
|
+
ClaimAmount,
|
|
26
|
+
ClaimItem,
|
|
27
|
+
ClaimKind,
|
|
28
|
+
ClaimPlan,
|
|
29
|
+
ClaimResult,
|
|
30
|
+
ClaimSkipped,
|
|
31
|
+
ClaimTx,
|
|
32
|
+
ClaimTxResult,
|
|
33
|
+
Claimable,
|
|
34
|
+
ClaimableOptions,
|
|
35
|
+
FarmProtocol,
|
|
36
|
+
} from '../rewards/types.js'
|
|
37
|
+
export type { LpProtocol } from '../lp.js'
|
|
38
|
+
export type { SignerInput, WriteResult, WriteStatus } from '../subpaths/write.js'
|
|
39
|
+
|
|
40
|
+
export interface GetClaimableOptions extends ClaimableOptions, ShortcutProviderOptions {}
|
|
41
|
+
|
|
42
|
+
/** 查一个地址能领取的手续费和挖矿奖励,节点参数与 getBalances 相同 */
|
|
43
|
+
export function getClaimable(owner: string, options: GetClaimableOptions = {}): Promise<Claimable> {
|
|
44
|
+
const { provider, overrides, own } = resolve(options, ['protocols', 'fees', 'rewards', 'v4', 'farms', 'gauges', 'maxPositions', 'prices', 'onPriceError', 'fetch'])
|
|
45
|
+
return claimable(provider, owner, { ...overrides, ...own })
|
|
46
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 交易模拟(子路径 `@w3lib/evm-batch-call/simulate`):发送前先看一笔(或一串依赖的)交易会发生什么——成不成功、gas、
|
|
3
|
+
* 哪些资产进出(含美元价值)、给了什么授权、calldata 解码、风险提示。可以直接传 `buildSwap` / `buildRevokes` / 流动性构建的交易。
|
|
4
|
+
* 不放在主入口,不用时打包不会带上这部分代码。EVM 用 `eth_simulateV1`(不支持时退回 `eth_call`),Tron 用 `triggerconstantcontract`。
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { getSimulation, getBatchSimulation } from '@w3lib/evm-batch-call/simulate'
|
|
8
|
+
*
|
|
9
|
+
* const sim = await getSimulation({ to: router, data, value }, { chainId: 1, from: user, usd: true })
|
|
10
|
+
* if (sim.warnings.some((w) => w.severity === 'danger')) alert(sim.warnings[0].message)
|
|
11
|
+
* const flow = await getBatchSimulation(plan.transactions, { chainId: 1, from: user }) // approve + swap,状态延续
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
import { simulate, simulateBatch, type BatchSimulationResult, type SimulateOptions, type SimulateTx, type SimulationResult } from '../simulate.js'
|
|
15
|
+
import { resolve, type ShortcutProviderOptions } from '../shortcuts.js'
|
|
16
|
+
|
|
17
|
+
export {
|
|
18
|
+
assertSimulation,
|
|
19
|
+
decodeCalldata,
|
|
20
|
+
decodeRevert,
|
|
21
|
+
simulate,
|
|
22
|
+
simulateBatch,
|
|
23
|
+
type ApprovalChange,
|
|
24
|
+
type BalanceChange,
|
|
25
|
+
type BatchSimulationResult,
|
|
26
|
+
type DecodedCall,
|
|
27
|
+
type DecodedType,
|
|
28
|
+
type SimulatedTransfer,
|
|
29
|
+
type SimulateOptions,
|
|
30
|
+
type SimulateTx,
|
|
31
|
+
type SimulationResult,
|
|
32
|
+
type SimulationWarning,
|
|
33
|
+
type StateOverrides,
|
|
34
|
+
type WarningSeverity,
|
|
35
|
+
} from '../simulate.js'
|
|
36
|
+
|
|
37
|
+
const OWN = ['from', 'watch', 'stateOverrides', 'gas', 'fee', 'usd', 'risk', 'forceCall'] as const
|
|
38
|
+
|
|
39
|
+
export interface GetSimulationOptions extends SimulateOptions, ShortcutProviderOptions {}
|
|
40
|
+
|
|
41
|
+
/** 模拟一笔交易,节点参数与 getBalances 相同 */
|
|
42
|
+
export function getSimulation(tx: SimulateTx, options: GetSimulationOptions = {}): Promise<SimulationResult> {
|
|
43
|
+
const { provider, overrides, own } = resolve(options, OWN)
|
|
44
|
+
return simulate(provider, tx, { ...own, ...(overrides.blockTag === undefined ? {} : { blockTag: overrides.blockTag }) })
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** 按顺序模拟一串依赖前一笔的交易(也可以直接传 buildSwap 等的结果),节点参数与 getBalances 相同 */
|
|
48
|
+
export function getBatchSimulation(txs: readonly SimulateTx[] | { transactions: readonly SimulateTx[] }, options: GetSimulationOptions = {}): Promise<BatchSimulationResult> {
|
|
49
|
+
const { provider, overrides, own } = resolve(options, OWN)
|
|
50
|
+
return simulateBatch(provider, txs, { ...own, ...(overrides.blockTag === undefined ? {} : { blockTag: overrides.blockTag }) })
|
|
51
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 智能账户批量执行(子路径 `@w3lib/evm-batch-call/smart-account`):ERC-4337(EntryPoint v0.7 / v0.8)UserOperation 的构建 / 哈希 / 签名、
|
|
3
|
+
* bundler 与 ERC-7677 paymaster 客户端、自己打包(handleOps)、EIP-5792(wallet_sendCalls)。
|
|
4
|
+
* 通常通过 `/write` 的 `mode: '4337' | '5792'`、`mode: '7702' + sponsor` 使用,这里是底层积木。
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { BundlerClient } from '@w3lib/evm-batch-call/smart-account'
|
|
8
|
+
* const bundler = new BundlerClient('https://public.pimlico.io/v2/8453/rpc')
|
|
9
|
+
* await bundler.supportedEntryPoints()
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export { BundlerClient, PaymasterClient, type GasEstimate, type PaymasterContext, type PaymasterFields, type PaymasterHook, type RpcClientOptions, type UserOperationReceipt } from '../smartAccount/clients.js'
|
|
13
|
+
export {
|
|
14
|
+
DUMMY_SIGNATURE,
|
|
15
|
+
EIP7702_MARKER,
|
|
16
|
+
ENTRY_POINT_V07,
|
|
17
|
+
ENTRY_POINT_V08,
|
|
18
|
+
entryPointAddress,
|
|
19
|
+
getUserOpHash,
|
|
20
|
+
packUserOp,
|
|
21
|
+
userOpToRpc,
|
|
22
|
+
userOpTypedData,
|
|
23
|
+
type EntryPointVersion,
|
|
24
|
+
type PackedUserOperation,
|
|
25
|
+
type UserOperation,
|
|
26
|
+
} from '../smartAccount/userOp.js'
|
|
27
|
+
import type { Provider } from '../provider.js'
|
|
28
|
+
import { WriteRpc } from '../write/rpc.js'
|
|
29
|
+
import { resolveSimpleAccount } from '../smartAccount/account.js'
|
|
30
|
+
import type { SmartAccountOptions } from '../smartAccount/send.js'
|
|
31
|
+
export { SIMPLE_ACCOUNT_FACTORY_V07, SIMPLE_ACCOUNT_FACTORY_V08, encodeExecuteBatch, type SmartAccountKind } from '../smartAccount/account.js'
|
|
32
|
+
export { getCallsStatus, getWalletCapabilities, sendCalls, waitForCalls, type CallsStatus, type Eip1193Like, type SendCallsRequest, type WalletCapabilities } from '../smartAccount/eip5792.js'
|
|
33
|
+
export type { SmartAccountOptions }
|
|
34
|
+
|
|
35
|
+
/** owner 对应的 SimpleAccount 地址(部署前就能算出,向它转入资产后再用 `mode: '4337'` 发送) */
|
|
36
|
+
export async function getSimpleAccount(provider: Provider, owner: string, options: Pick<SmartAccountOptions, 'entryPoint' | 'salt' | 'factory'> = {}): Promise<{ address: string; deployed: boolean }> {
|
|
37
|
+
const rpc = await WriteRpc.from(provider)
|
|
38
|
+
const { address, deployed } = await resolveSimpleAccount(rpc, owner, options.entryPoint ?? '0.7', options.salt, options.factory)
|
|
39
|
+
return { address, deployed }
|
|
40
|
+
}
|