@agentlayer.tech/wallet 0.1.92 → 0.1.94
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/.openclaw/extensions/agent-wallet/dist/index.js +41 -0
- package/.openclaw/extensions/agent-wallet/index.ts +41 -0
- package/.openclaw/extensions/agent-wallet/openclaw.plugin.json +4 -1
- package/.openclaw/extensions/agent-wallet/package.json +1 -1
- package/CHANGELOG.md +35 -0
- package/VERSION +1 -1
- package/agent-wallet/agent_wallet/__init__.py +1 -1
- package/agent-wallet/agent_wallet/autonomous_permissions.py +1 -0
- package/agent-wallet/agent_wallet/openclaw_adapter.py +136 -0
- package/agent-wallet/agent_wallet/providers/wdk_evm_local.py +2 -0
- package/agent-wallet/agent_wallet/providers/x402.py +9 -1
- package/agent-wallet/agent_wallet/user_wallets.py +2 -0
- package/agent-wallet/agent_wallet/wallet_layer/base.py +18 -0
- package/agent-wallet/agent_wallet/wallet_layer/solana.py +2 -0
- package/agent-wallet/agent_wallet/wallet_layer/wdk_evm.py +97 -0
- package/agent-wallet/openclaw.plugin.json +1 -1
- package/agent-wallet/pyproject.toml +1 -1
- package/claude-code/plugins/agent-wallet/.claude-plugin/plugin.json +1 -1
- package/claude-code/plugins/agent-wallet/README.md +2 -0
- package/claude-code/plugins/agent-wallet/commands/cards.md +129 -0
- package/codex/plugins/agent-wallet/.codex-plugin/plugin.json +1 -1
- package/codex/plugins/agent-wallet/README.md +6 -2
- package/codex/plugins/agent-wallet/server.py +1 -0
- package/codex/plugins/agent-wallet/skills/cards/SKILL.md +119 -0
- package/hermes/plugins/agent_wallet/plugin.yaml +1 -1
- package/package.json +1 -1
- package/wdk-btc-wallet/package.json +1 -1
- package/wdk-evm-wallet/.env.example +3 -0
- package/wdk-evm-wallet/README.md +6 -0
- package/wdk-evm-wallet/package.json +1 -1
- package/wdk-evm-wallet/src/config.js +9 -0
- package/wdk-evm-wallet/src/server.js +12 -0
- package/wdk-evm-wallet/src/wdk_evm_wallet.js +345 -0
|
@@ -23,6 +23,28 @@ const DEFAULT_LIFI_SLIPPAGE = 0.005;
|
|
|
23
23
|
const ALWAYS_DENIED_LIFI_BRIDGES = ["mayan"];
|
|
24
24
|
const PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
25
25
|
const UNISWAP_SUPPORTED_CHAIN_IDS = { ethereum: 1, base: 8453, robinhood: 4663 };
|
|
26
|
+
const UNISWAP_LIQUIDITY_ACTIONS = new Set(["create", "increase", "decrease", "claim_fees"]);
|
|
27
|
+
const UNISWAP_LIQUIDITY_PROTOCOLS = new Set(["V3", "V4"]);
|
|
28
|
+
// LP API transactions are accepted only for these official per-chain position
|
|
29
|
+
// managers. Keeping the list here makes the local signer a narrow protocol
|
|
30
|
+
// integration rather than a generic calldata relay.
|
|
31
|
+
const UNISWAP_LIQUIDITY_POSITION_MANAGERS = {
|
|
32
|
+
ethereum: {
|
|
33
|
+
V3: "0xc36442b4a4522e871399cd717abdd847ab11fe88",
|
|
34
|
+
V4: "0xbd216513d74c8cf14cf4747e6aaa6420ff64ee9e",
|
|
35
|
+
},
|
|
36
|
+
base: {
|
|
37
|
+
V3: "0x03a520b32c04bf3beef7beb72e919cf822ed34f1",
|
|
38
|
+
V4: "0x7c5f5a4bbd8fd63184577525326123b519429bdc",
|
|
39
|
+
},
|
|
40
|
+
robinhood: {
|
|
41
|
+
V3: "0x73991a25c818bf1f1128deaab1492d45638de0d3",
|
|
42
|
+
V4: "0x58daec3116aae6d93017baaea7749052e8a04fa7",
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
const ERC20_APPROVE_INTERFACE = new Interface([
|
|
46
|
+
"function approve(address spender,uint256 amount) returns (bool)",
|
|
47
|
+
]);
|
|
26
48
|
// Every executable path is declared here rather than inferred from a Trading
|
|
27
49
|
// API response. A new chain/router version therefore requires an explicit,
|
|
28
50
|
// reviewed allow-list entry before it can receive a signed transaction.
|
|
@@ -925,6 +947,31 @@ function assertUniswapSupportedNetwork(network) {
|
|
|
925
947
|
return chainId;
|
|
926
948
|
}
|
|
927
949
|
|
|
950
|
+
function normalizeUniswapLiquidityAction(value) {
|
|
951
|
+
const action = String(value || "").trim().toLowerCase();
|
|
952
|
+
if (!UNISWAP_LIQUIDITY_ACTIONS.has(action)) {
|
|
953
|
+
throw new Error("Uniswap liquidity action must be create, increase, decrease, or claim_fees.");
|
|
954
|
+
}
|
|
955
|
+
return action;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
function normalizeUniswapLiquidityProtocol(value) {
|
|
959
|
+
const protocol = String(value || "").trim().toUpperCase();
|
|
960
|
+
if (!UNISWAP_LIQUIDITY_PROTOCOLS.has(protocol)) {
|
|
961
|
+
throw new Error("Uniswap liquidity protocol must be V3 or V4.");
|
|
962
|
+
}
|
|
963
|
+
return protocol;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
function getUniswapLiquidityPositionManager(network, protocol) {
|
|
967
|
+
assertUniswapSupportedNetwork(network);
|
|
968
|
+
const manager = UNISWAP_LIQUIDITY_POSITION_MANAGERS[network]?.[protocol];
|
|
969
|
+
if (!manager) {
|
|
970
|
+
throw new Error(`Uniswap ${protocol} liquidity is not configured for ${network}.`);
|
|
971
|
+
}
|
|
972
|
+
return manager;
|
|
973
|
+
}
|
|
974
|
+
|
|
928
975
|
function getUniswapNetworkExecutionProfile(network) {
|
|
929
976
|
const profile = UNISWAP_EXECUTION_PROFILES[network];
|
|
930
977
|
if (!profile) {
|
|
@@ -5743,6 +5790,304 @@ export class WdkEvmWalletService {
|
|
|
5743
5790
|
return payload;
|
|
5744
5791
|
}
|
|
5745
5792
|
|
|
5793
|
+
async #uniswapLiquidityApiRequest(action, body) {
|
|
5794
|
+
const normalizedAction = String(action || "").trim().toLowerCase();
|
|
5795
|
+
const headers = { "Content-Type": "application/json", Accept: "application/json" };
|
|
5796
|
+
if (this.config.uniswapLiquidityViaGateway) {
|
|
5797
|
+
const token = String(this.config.providerGatewayToken || "").trim();
|
|
5798
|
+
if (token) {
|
|
5799
|
+
headers.Authorization = `Bearer ${token}`;
|
|
5800
|
+
}
|
|
5801
|
+
} else {
|
|
5802
|
+
if (!this.config.uniswapApiKey) {
|
|
5803
|
+
throw createTaggedError(
|
|
5804
|
+
"UNISWAP_API_KEY is not configured. Set it, or route Uniswap through the provider gateway, to use liquidity operations.",
|
|
5805
|
+
"uniswap_api_key_missing",
|
|
5806
|
+
{ provider: "uniswap" }
|
|
5807
|
+
);
|
|
5808
|
+
}
|
|
5809
|
+
headers["x-api-key"] = this.config.uniswapApiKey;
|
|
5810
|
+
}
|
|
5811
|
+
const base = String(this.config.uniswapLiquidityApiBaseUrl).replace(/\/+$/, "");
|
|
5812
|
+
const suffix = this.config.uniswapLiquidityViaGateway ? `/${normalizedAction}` : `/lp/${normalizedAction}`;
|
|
5813
|
+
let response;
|
|
5814
|
+
try {
|
|
5815
|
+
response = await fetch(`${base}${suffix}`, { method: "POST", headers, body: JSON.stringify(body) });
|
|
5816
|
+
} catch (error) {
|
|
5817
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
5818
|
+
throw createTaggedError(`Uniswap liquidity API unavailable: ${message}`, "network_unavailable", {
|
|
5819
|
+
provider: "uniswap",
|
|
5820
|
+
action: normalizedAction,
|
|
5821
|
+
});
|
|
5822
|
+
}
|
|
5823
|
+
let payload;
|
|
5824
|
+
try {
|
|
5825
|
+
payload = await response.json();
|
|
5826
|
+
} catch {
|
|
5827
|
+
payload = null;
|
|
5828
|
+
}
|
|
5829
|
+
if (!response.ok || !payload || typeof payload !== "object") {
|
|
5830
|
+
throw createTaggedError(
|
|
5831
|
+
String(payload?.message || payload?.error || `Uniswap liquidity ${normalizedAction} failed with HTTP ${response.status}.`),
|
|
5832
|
+
"network_unavailable",
|
|
5833
|
+
{ provider: "uniswap", action: normalizedAction, httpStatus: response.status }
|
|
5834
|
+
);
|
|
5835
|
+
}
|
|
5836
|
+
return payload;
|
|
5837
|
+
}
|
|
5838
|
+
|
|
5839
|
+
#buildUniswapLiquidityRequest({ action, protocol, address, request }) {
|
|
5840
|
+
const body = { ...(request && typeof request === "object" ? request : {}) };
|
|
5841
|
+
// Caller cannot select identity, chain or simulator behavior. These are set
|
|
5842
|
+
// locally to make every preview/send reproducible through the active wallet.
|
|
5843
|
+
body.walletAddress = address;
|
|
5844
|
+
body.protocol = protocol;
|
|
5845
|
+
body.simulateTransaction = true;
|
|
5846
|
+
delete body.signature;
|
|
5847
|
+
delete body.batchPermitData;
|
|
5848
|
+
delete body.v4BatchPermitData;
|
|
5849
|
+
delete body.v3NftPermitData;
|
|
5850
|
+
if (action === "claim_fees") {
|
|
5851
|
+
delete body.independentToken;
|
|
5852
|
+
}
|
|
5853
|
+
return body;
|
|
5854
|
+
}
|
|
5855
|
+
|
|
5856
|
+
#extractUniswapLiquidityTransaction(payload, action) {
|
|
5857
|
+
const field = action === "create" ? "create" : action === "increase" ? "increase" : action === "decrease" ? "decrease" : "claim";
|
|
5858
|
+
const tx = payload?.[field] || payload?.transaction;
|
|
5859
|
+
if (!tx || typeof tx !== "object") {
|
|
5860
|
+
throw createTaggedError("Uniswap liquidity API returned no executable transaction.", "network_unavailable", {
|
|
5861
|
+
provider: "uniswap",
|
|
5862
|
+
action,
|
|
5863
|
+
});
|
|
5864
|
+
}
|
|
5865
|
+
return tx;
|
|
5866
|
+
}
|
|
5867
|
+
|
|
5868
|
+
async #getUniswapLiquidityApprovals({ runtimeConfig, protocol, action, address, payload }) {
|
|
5869
|
+
if (action !== "create" && action !== "increase") {
|
|
5870
|
+
return [];
|
|
5871
|
+
}
|
|
5872
|
+
const lpTokens = [payload?.token0, payload?.token1]
|
|
5873
|
+
.filter((token) => token && typeof token === "object")
|
|
5874
|
+
// The LP API represents native ETH with the zero-address sentinel. It
|
|
5875
|
+
// cannot have an ERC-20 allowance, so exclude it from check_approval.
|
|
5876
|
+
.filter((token) => !isZeroAddress(String(token.tokenAddress || "")))
|
|
5877
|
+
.map((token) => {
|
|
5878
|
+
const amount = BigInt(assertNonNegativeBigIntString(token.amount, "lp token amount"));
|
|
5879
|
+
return {
|
|
5880
|
+
tokenAddress: normalizeAddress(String(token.tokenAddress || ""), "lp token address"),
|
|
5881
|
+
amount,
|
|
5882
|
+
};
|
|
5883
|
+
})
|
|
5884
|
+
// Concentrated positions can legitimately be single-sided while the
|
|
5885
|
+
// current price lies outside their selected range. A zero contribution
|
|
5886
|
+
// has no ERC-20 allowance requirement and must not block the LP action.
|
|
5887
|
+
.filter((token) => token.amount > 0n)
|
|
5888
|
+
.map((token) => ({ ...token, amount: token.amount.toString() }));
|
|
5889
|
+
if (!lpTokens.length) {
|
|
5890
|
+
return [];
|
|
5891
|
+
}
|
|
5892
|
+
const expectedTokens = new Set(
|
|
5893
|
+
lpTokens.map((token) => String(token.tokenAddress).toLowerCase())
|
|
5894
|
+
);
|
|
5895
|
+
const approvalPayload = await this.#uniswapLiquidityApiRequest("check_approval", {
|
|
5896
|
+
walletAddress: address,
|
|
5897
|
+
chainId: runtimeConfig.chainId,
|
|
5898
|
+
protocol,
|
|
5899
|
+
lpTokens,
|
|
5900
|
+
action: action.toUpperCase(),
|
|
5901
|
+
// The initial version uses ordinary, bounded approval transactions. This
|
|
5902
|
+
// keeps the send path observable and avoids requiring an extra signature
|
|
5903
|
+
// protocol before LP workflows have seen live use.
|
|
5904
|
+
generatePermitAsTransaction: true,
|
|
5905
|
+
});
|
|
5906
|
+
const transactions = Array.isArray(approvalPayload.transactions) ? approvalPayload.transactions : [];
|
|
5907
|
+
return transactions.map((item, index) => {
|
|
5908
|
+
const raw = item?.transaction;
|
|
5909
|
+
if (!raw || typeof raw !== "object") {
|
|
5910
|
+
throw createTaggedError("Uniswap liquidity approval response is malformed.", "uniswap_liquidity_invalid_approval", { index });
|
|
5911
|
+
}
|
|
5912
|
+
const to = normalizeAddress(String(raw.to || ""), "liquidity approval.to");
|
|
5913
|
+
if (!expectedTokens.has(to.toLowerCase())) {
|
|
5914
|
+
throw createTaggedError("Uniswap liquidity approval is for a token outside this LP request.", "uniswap_liquidity_unexpected_token", { to });
|
|
5915
|
+
}
|
|
5916
|
+
const data = assertNonEmptyString(String(raw.data || ""), "liquidity approval.data");
|
|
5917
|
+
if (parseHexOrDecimalBigInt(raw.value || "0", "liquidity approval.value") !== 0n) {
|
|
5918
|
+
throw createTaggedError("Uniswap liquidity approval must not transfer native value.", "uniswap_liquidity_invalid_approval", { to });
|
|
5919
|
+
}
|
|
5920
|
+
if (raw.chainId !== undefined && Number(raw.chainId) !== runtimeConfig.chainId) {
|
|
5921
|
+
throw createTaggedError("Uniswap liquidity approval has the wrong chain id.", "uniswap_liquidity_chain_mismatch");
|
|
5922
|
+
}
|
|
5923
|
+
if (raw.from && normalizeAddress(String(raw.from), "liquidity approval.from").toLowerCase() !== address.toLowerCase()) {
|
|
5924
|
+
throw createTaggedError("Uniswap liquidity approval sender does not match the active wallet.", "uniswap_liquidity_sender_mismatch");
|
|
5925
|
+
}
|
|
5926
|
+
let decoded;
|
|
5927
|
+
try {
|
|
5928
|
+
decoded = ERC20_APPROVE_INTERFACE.parseTransaction({ data });
|
|
5929
|
+
} catch {
|
|
5930
|
+
decoded = null;
|
|
5931
|
+
}
|
|
5932
|
+
if (!decoded || decoded.name !== "approve") {
|
|
5933
|
+
throw createTaggedError("Uniswap liquidity approval is not a bounded ERC-20 approve call.", "uniswap_liquidity_invalid_approval", { to });
|
|
5934
|
+
}
|
|
5935
|
+
const spender = normalizeAddress(String(decoded.args[0]), "liquidity approval spender").toLowerCase();
|
|
5936
|
+
const amount = BigInt(decoded.args[1]);
|
|
5937
|
+
const positionManager = getUniswapLiquidityPositionManager(runtimeConfig.network, protocol);
|
|
5938
|
+
if (spender !== positionManager && spender !== PERMIT2_ADDRESS.toLowerCase()) {
|
|
5939
|
+
throw createTaggedError("Uniswap liquidity approval has an unexpected spender.", "uniswap_liquidity_unexpected_spender", { spender, positionManager });
|
|
5940
|
+
}
|
|
5941
|
+
if (amount <= 0n || amount >= (2n ** 255n)) {
|
|
5942
|
+
throw createTaggedError("Uniswap liquidity approval must use a bounded amount.", "uniswap_liquidity_unbounded_approval", { spender });
|
|
5943
|
+
}
|
|
5944
|
+
return {
|
|
5945
|
+
tx: { to, data, value: 0n },
|
|
5946
|
+
token: to,
|
|
5947
|
+
spender,
|
|
5948
|
+
amount,
|
|
5949
|
+
action: String(item?.action || action).toUpperCase(),
|
|
5950
|
+
};
|
|
5951
|
+
});
|
|
5952
|
+
}
|
|
5953
|
+
|
|
5954
|
+
#validateUniswapLiquidityTransaction({ runtimeConfig, protocol, address, transaction }) {
|
|
5955
|
+
const to = normalizeAddress(String(transaction.to || ""), "liquidity transaction.to");
|
|
5956
|
+
const expectedManager = getUniswapLiquidityPositionManager(runtimeConfig.network, protocol);
|
|
5957
|
+
if (to.toLowerCase() !== expectedManager) {
|
|
5958
|
+
throw createTaggedError("Uniswap liquidity API returned an unexpected PositionManager.", "uniswap_unexpected_position_manager", {
|
|
5959
|
+
expected: expectedManager,
|
|
5960
|
+
actual: to.toLowerCase(),
|
|
5961
|
+
network: runtimeConfig.network,
|
|
5962
|
+
protocol,
|
|
5963
|
+
});
|
|
5964
|
+
}
|
|
5965
|
+
if (transaction.chainId !== undefined && Number(transaction.chainId) !== runtimeConfig.chainId) {
|
|
5966
|
+
throw createTaggedError("Uniswap liquidity transaction has the wrong chain id.", "uniswap_liquidity_chain_mismatch", {
|
|
5967
|
+
expected: runtimeConfig.chainId,
|
|
5968
|
+
actual: transaction.chainId,
|
|
5969
|
+
});
|
|
5970
|
+
}
|
|
5971
|
+
if (transaction.from && normalizeAddress(String(transaction.from), "liquidity transaction.from").toLowerCase() !== address.toLowerCase()) {
|
|
5972
|
+
throw createTaggedError("Uniswap liquidity transaction sender does not match the active wallet.", "uniswap_liquidity_sender_mismatch");
|
|
5973
|
+
}
|
|
5974
|
+
const data = assertNonEmptyString(String(transaction.data || ""), "liquidity transaction.data");
|
|
5975
|
+
if (!/^0x[0-9a-fA-F]+$/.test(data) || data.length < 10) {
|
|
5976
|
+
throw createTaggedError("Uniswap liquidity transaction calldata is invalid.", "uniswap_liquidity_invalid_calldata");
|
|
5977
|
+
}
|
|
5978
|
+
return { to, data, value: parseHexOrDecimalBigInt(transaction.value || "0", "liquidity transaction.value") };
|
|
5979
|
+
}
|
|
5980
|
+
|
|
5981
|
+
#formatUniswapLiquidityResponse({ runtimeConfig, accountIndex, address, action, protocol, request, payload, transaction, approvals = [], simulation = null }) {
|
|
5982
|
+
const tx = transaction ? {
|
|
5983
|
+
to: transaction.to,
|
|
5984
|
+
value: transaction.value.toString(),
|
|
5985
|
+
dataHash: sha256Hex(transaction.data),
|
|
5986
|
+
} : null;
|
|
5987
|
+
return {
|
|
5988
|
+
network: runtimeConfig.network,
|
|
5989
|
+
chainId: runtimeConfig.chainId,
|
|
5990
|
+
accountIndex,
|
|
5991
|
+
address,
|
|
5992
|
+
protocol: "uniswap",
|
|
5993
|
+
liquidityAction: action,
|
|
5994
|
+
liquidityProtocol: protocol,
|
|
5995
|
+
request,
|
|
5996
|
+
requestId: String(payload?.requestId || "").trim() || null,
|
|
5997
|
+
token0: payload?.token0 || null,
|
|
5998
|
+
token1: payload?.token1 || null,
|
|
5999
|
+
tickLower: payload?.tickLower ?? null,
|
|
6000
|
+
tickUpper: payload?.tickUpper ?? null,
|
|
6001
|
+
adjustedMinPrice: payload?.adjustedMinPrice ?? null,
|
|
6002
|
+
adjustedMaxPrice: payload?.adjustedMaxPrice ?? null,
|
|
6003
|
+
gasFee: payload?.gasFee ?? null,
|
|
6004
|
+
positionTokenId: String(request?.nftTokenId || request?.tokenId || "").trim() || null,
|
|
6005
|
+
positionManager: getUniswapLiquidityPositionManager(runtimeConfig.network, protocol),
|
|
6006
|
+
approvals: approvals.map((approval) => ({
|
|
6007
|
+
token: approval.token,
|
|
6008
|
+
spender: approval.spender,
|
|
6009
|
+
amount: approval.amount.toString(),
|
|
6010
|
+
action: approval.action,
|
|
6011
|
+
})),
|
|
6012
|
+
transaction: tx,
|
|
6013
|
+
simulation,
|
|
6014
|
+
source: "uniswap-liquidity-api",
|
|
6015
|
+
};
|
|
6016
|
+
}
|
|
6017
|
+
|
|
6018
|
+
async quoteUniswapLiquidity({ seedPhrase, address, action, protocol, request, accountIndex = 0, network }) {
|
|
6019
|
+
return this.#withReadableAccount({ seedPhrase, address, accountIndex, network }, async (account, runtimeConfig) => {
|
|
6020
|
+
assertUniswapSupportedNetwork(runtimeConfig.network);
|
|
6021
|
+
const normalizedAction = normalizeUniswapLiquidityAction(action);
|
|
6022
|
+
const normalizedProtocol = normalizeUniswapLiquidityProtocol(protocol);
|
|
6023
|
+
const walletAddress = await account.getAddress();
|
|
6024
|
+
const body = this.#buildUniswapLiquidityRequest({ action: normalizedAction, protocol: normalizedProtocol, address: walletAddress, request });
|
|
6025
|
+
body.chainId = runtimeConfig.chainId;
|
|
6026
|
+
const payload = await this.#uniswapLiquidityApiRequest(normalizedAction, body);
|
|
6027
|
+
const transaction = this.#validateUniswapLiquidityTransaction({
|
|
6028
|
+
runtimeConfig,
|
|
6029
|
+
protocol: normalizedProtocol,
|
|
6030
|
+
address: walletAddress,
|
|
6031
|
+
transaction: this.#extractUniswapLiquidityTransaction(payload, normalizedAction),
|
|
6032
|
+
});
|
|
6033
|
+
const approvals = await this.#getUniswapLiquidityApprovals({ runtimeConfig, protocol: normalizedProtocol, action: normalizedAction, address: walletAddress, payload });
|
|
6034
|
+
const simulation = await this.#simulatePreparedTransaction({ runtimeConfig, from: walletAddress, tx: transaction, operationLabel: "Uniswap liquidity" });
|
|
6035
|
+
return this.#formatUniswapLiquidityResponse({ runtimeConfig, accountIndex, address: walletAddress, action: normalizedAction, protocol: normalizedProtocol, request: body, payload, transaction, approvals, simulation });
|
|
6036
|
+
});
|
|
6037
|
+
}
|
|
6038
|
+
|
|
6039
|
+
async sendUniswapLiquidity({ seedPhrase, action, protocol, request, accountIndex = 0, network }) {
|
|
6040
|
+
return this.#withAccount({ seedPhrase, accountIndex, network }, async (account, runtimeConfig) => {
|
|
6041
|
+
assertUniswapSupportedNetwork(runtimeConfig.network);
|
|
6042
|
+
const normalizedAction = normalizeUniswapLiquidityAction(action);
|
|
6043
|
+
const normalizedProtocol = normalizeUniswapLiquidityProtocol(protocol);
|
|
6044
|
+
const address = await account.getAddress();
|
|
6045
|
+
// Rebuild immediately before signing: price/ticks and calldata can change
|
|
6046
|
+
// while an intent approval is being reviewed.
|
|
6047
|
+
const body = this.#buildUniswapLiquidityRequest({ action: normalizedAction, protocol: normalizedProtocol, address, request });
|
|
6048
|
+
body.chainId = runtimeConfig.chainId;
|
|
6049
|
+
let payload = await this.#uniswapLiquidityApiRequest(normalizedAction, body);
|
|
6050
|
+
let transaction = this.#validateUniswapLiquidityTransaction({
|
|
6051
|
+
runtimeConfig,
|
|
6052
|
+
protocol: normalizedProtocol,
|
|
6053
|
+
address,
|
|
6054
|
+
transaction: this.#extractUniswapLiquidityTransaction(payload, normalizedAction),
|
|
6055
|
+
});
|
|
6056
|
+
const approvals = await this.#getUniswapLiquidityApprovals({ runtimeConfig, protocol: normalizedProtocol, action: normalizedAction, address, payload });
|
|
6057
|
+
const approvalResults = [];
|
|
6058
|
+
for (const approval of approvals) {
|
|
6059
|
+
const approvalSimulation = await this.#simulatePreparedTransaction({ runtimeConfig, from: address, tx: approval.tx, operationLabel: "Uniswap liquidity approval" });
|
|
6060
|
+
this.#assertSimulationSucceeded(approvalSimulation);
|
|
6061
|
+
const approvalResult = await this.#sendBufferedDefiTransaction({ account, runtimeConfig, from: address, tx: approval.tx, operationLabel: "Uniswap liquidity approval" });
|
|
6062
|
+
await this.#waitForTransactionReceipt(runtimeConfig, approvalResult.hash, { operationLabel: "Uniswap liquidity approval", failureCode: "uniswap_liquidity_approval_reverted", timeoutCode: "uniswap_liquidity_approval_timeout" });
|
|
6063
|
+
approvalResults.push({ token: approval.token, spender: approval.spender, amount: approval.amount.toString(), hash: approvalResult.hash });
|
|
6064
|
+
}
|
|
6065
|
+
if (approvals.length) {
|
|
6066
|
+
payload = await this.#uniswapLiquidityApiRequest(normalizedAction, body);
|
|
6067
|
+
transaction = this.#validateUniswapLiquidityTransaction({
|
|
6068
|
+
runtimeConfig,
|
|
6069
|
+
protocol: normalizedProtocol,
|
|
6070
|
+
address,
|
|
6071
|
+
transaction: this.#extractUniswapLiquidityTransaction(payload, normalizedAction),
|
|
6072
|
+
});
|
|
6073
|
+
}
|
|
6074
|
+
const simulation = await this.#simulatePreparedTransaction({ runtimeConfig, from: address, tx: transaction, operationLabel: "Uniswap liquidity" });
|
|
6075
|
+
this.#assertSimulationSucceeded(simulation);
|
|
6076
|
+
const result = await this.#sendBufferedDefiTransaction({ account, runtimeConfig, from: address, tx: transaction, operationLabel: "Uniswap liquidity" });
|
|
6077
|
+
await this.#waitForTransactionReceipt(runtimeConfig, result.hash, {
|
|
6078
|
+
operationLabel: "Uniswap liquidity",
|
|
6079
|
+
failureCode: "uniswap_liquidity_reverted",
|
|
6080
|
+
timeoutCode: "uniswap_liquidity_confirmation_timeout",
|
|
6081
|
+
});
|
|
6082
|
+
return {
|
|
6083
|
+
...this.#formatUniswapLiquidityResponse({ runtimeConfig, accountIndex, address, action: normalizedAction, protocol: normalizedProtocol, request: body, payload, transaction, approvals, simulation }),
|
|
6084
|
+
result,
|
|
6085
|
+
approvalResults,
|
|
6086
|
+
confirmed: true,
|
|
6087
|
+
};
|
|
6088
|
+
});
|
|
6089
|
+
}
|
|
6090
|
+
|
|
5746
6091
|
async #fetchUniswapQuote({ runtimeConfig, routerProfile, address, swapRequest }) {
|
|
5747
6092
|
const chainId = UNISWAP_SUPPORTED_CHAIN_IDS[runtimeConfig.network];
|
|
5748
6093
|
const quoteRequest = {
|