@liquidium/client 0.4.1 → 0.5.0-rc.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/README.md +75 -48
- package/dist/index.cjs +1088 -413
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +327 -275
- package/dist/index.d.ts +327 -275
- package/dist/index.js +1087 -414
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6,60 +6,12 @@ var agent = require('@icp-sdk/core/agent');
|
|
|
6
6
|
var principal = require('@icp-sdk/core/principal');
|
|
7
7
|
var base = require('@scure/base');
|
|
8
8
|
var candid = require('@icp-sdk/core/candid');
|
|
9
|
+
var icp = require('@icp-sdk/canisters/ledger/icp');
|
|
9
10
|
var icrc = require('@icp-sdk/canisters/ledger/icrc');
|
|
10
11
|
var bitcoinAddressValidation = require('bitcoin-address-validation');
|
|
11
12
|
|
|
12
13
|
// src/client.ts
|
|
13
14
|
|
|
14
|
-
// src/core/types.ts
|
|
15
|
-
var Environment = {
|
|
16
|
-
mainnet: "mainnet"
|
|
17
|
-
};
|
|
18
|
-
var Asset = {
|
|
19
|
-
BTC: "BTC",
|
|
20
|
-
SOL: "SOL",
|
|
21
|
-
USDC: "USDC",
|
|
22
|
-
USDT: "USDT"
|
|
23
|
-
};
|
|
24
|
-
var Chain = {
|
|
25
|
-
BTC: "BTC",
|
|
26
|
-
ETH: "ETH"
|
|
27
|
-
};
|
|
28
|
-
var SupplyAction = {
|
|
29
|
-
deposit: "deposit",
|
|
30
|
-
repayment: "repayment"
|
|
31
|
-
};
|
|
32
|
-
var OutflowType = {
|
|
33
|
-
borrow: "borrow",
|
|
34
|
-
feeClaim: "feeClaim",
|
|
35
|
-
withdrawal: "withdrawal"
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
// src/core/config.ts
|
|
39
|
-
var MAINNET_HOST = "https://icp-api.io";
|
|
40
|
-
var DEFAULT_API_BASE_URL = "https://app.liquidium.fi/api/sdk";
|
|
41
|
-
var DEFAULT_ENVIRONMENT = Environment.mainnet;
|
|
42
|
-
var MAINNET_CANISTER_IDS = {
|
|
43
|
-
lending: "hyk4r-jqaaa-aaaar-qb4ca-cai",
|
|
44
|
-
btcPool: "hkmli-faaaa-aaaar-qb4ba-cai",
|
|
45
|
-
ercPool: "hnnn4-iyaaa-aaaar-qb4bq-cai",
|
|
46
|
-
ethDeposit: "z5jz7-nyaaa-aaaar-qb6pq-cai",
|
|
47
|
-
instantLoans: "u5rm3-niaaa-aaaar-qb7eq-cai"
|
|
48
|
-
};
|
|
49
|
-
var CANISTER_IDS_BY_ENVIRONMENT = {
|
|
50
|
-
mainnet: MAINNET_CANISTER_IDS
|
|
51
|
-
};
|
|
52
|
-
function resolveHost(override) {
|
|
53
|
-
return override ?? MAINNET_HOST;
|
|
54
|
-
}
|
|
55
|
-
function resolveCanisterIds(environment = DEFAULT_ENVIRONMENT, overrides) {
|
|
56
|
-
return { ...CANISTER_IDS_BY_ENVIRONMENT[environment], ...overrides };
|
|
57
|
-
}
|
|
58
|
-
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
59
|
-
var CK_CANISTER_IDS = {
|
|
60
|
-
btcMinter: "mqygn-kiaaa-aaaar-qaadq-cai",
|
|
61
|
-
btcLedger: "mxzaz-hqaaa-aaaar-qaada-cai"};
|
|
62
|
-
|
|
63
15
|
// src/core/errors.ts
|
|
64
16
|
var LiquidiumErrorCode = {
|
|
65
17
|
// Protocol errors
|
|
@@ -130,6 +82,127 @@ var LiquidiumError = class extends Error {
|
|
|
130
82
|
}
|
|
131
83
|
};
|
|
132
84
|
|
|
85
|
+
// src/core/types.ts
|
|
86
|
+
var Environment = {
|
|
87
|
+
mainnet: "mainnet"
|
|
88
|
+
};
|
|
89
|
+
var Asset = {
|
|
90
|
+
BTC: "BTC",
|
|
91
|
+
ICP: "ICP",
|
|
92
|
+
USDC: "USDC",
|
|
93
|
+
USDT: "USDT"
|
|
94
|
+
};
|
|
95
|
+
var Chain = {
|
|
96
|
+
BTC: "BTC",
|
|
97
|
+
ETH: "ETH",
|
|
98
|
+
ICP: "ICP"
|
|
99
|
+
};
|
|
100
|
+
function isAssetIdentifier(identifier) {
|
|
101
|
+
switch (identifier.chain) {
|
|
102
|
+
case Chain.BTC:
|
|
103
|
+
return identifier.asset === Asset.BTC;
|
|
104
|
+
case Chain.ETH:
|
|
105
|
+
return identifier.asset === Asset.USDC || identifier.asset === Asset.USDT;
|
|
106
|
+
case Chain.ICP:
|
|
107
|
+
return identifier.asset === Asset.BTC || identifier.asset === Asset.ICP || identifier.asset === Asset.USDC || identifier.asset === Asset.USDT;
|
|
108
|
+
default:
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
var SupplyAction = {
|
|
113
|
+
deposit: "deposit",
|
|
114
|
+
repayment: "repayment"
|
|
115
|
+
};
|
|
116
|
+
var OutflowType = {
|
|
117
|
+
borrow: "borrow",
|
|
118
|
+
feeClaim: "feeClaim",
|
|
119
|
+
withdrawal: "withdrawal"
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// src/core/config.ts
|
|
123
|
+
var MAINNET_HOST = "https://icp-api.io";
|
|
124
|
+
var DEFAULT_API_BASE_URL = "https://app.liquidium.fi/api/sdk";
|
|
125
|
+
var DEFAULT_ENVIRONMENT = Environment.mainnet;
|
|
126
|
+
var MAINNET_CANISTER_IDS = {
|
|
127
|
+
lending: "hyk4r-jqaaa-aaaar-qb4ca-cai",
|
|
128
|
+
pools: {
|
|
129
|
+
btc: "hkmli-faaaa-aaaar-qb4ba-cai",
|
|
130
|
+
usdt: "hnnn4-iyaaa-aaaar-qb4bq-cai",
|
|
131
|
+
usdc: "6sna2-oiaaa-aaaar-qb66q-cai",
|
|
132
|
+
icp: "r2pk3-4yaaa-aaaar-qb7zq-cai"
|
|
133
|
+
},
|
|
134
|
+
ethDeposit: "z5jz7-nyaaa-aaaar-qb6pq-cai",
|
|
135
|
+
instantLoans: "u5rm3-niaaa-aaaar-qb7eq-cai"
|
|
136
|
+
};
|
|
137
|
+
var CANISTER_IDS_BY_ENVIRONMENT = {
|
|
138
|
+
mainnet: MAINNET_CANISTER_IDS
|
|
139
|
+
};
|
|
140
|
+
var SUPPORTED_CANISTER_ID_OVERRIDE_KEYS = /* @__PURE__ */ new Set([
|
|
141
|
+
"lending",
|
|
142
|
+
"pools",
|
|
143
|
+
"ethDeposit",
|
|
144
|
+
"instantLoans"
|
|
145
|
+
]);
|
|
146
|
+
var SUPPORTED_POOL_CANISTER_ID_OVERRIDE_KEYS = /* @__PURE__ */ new Set([
|
|
147
|
+
"btc",
|
|
148
|
+
"usdt",
|
|
149
|
+
"usdc",
|
|
150
|
+
"icp"
|
|
151
|
+
]);
|
|
152
|
+
function resolveHost(override) {
|
|
153
|
+
return override ?? MAINNET_HOST;
|
|
154
|
+
}
|
|
155
|
+
function resolveCanisterIds(environment = DEFAULT_ENVIRONMENT, overrides) {
|
|
156
|
+
const defaults = CANISTER_IDS_BY_ENVIRONMENT[environment];
|
|
157
|
+
validateCanisterIdOverrides(overrides);
|
|
158
|
+
const pools = {
|
|
159
|
+
...defaults.pools,
|
|
160
|
+
...overrides?.pools
|
|
161
|
+
};
|
|
162
|
+
return {
|
|
163
|
+
lending: overrides?.lending ?? defaults.lending,
|
|
164
|
+
pools,
|
|
165
|
+
ethDeposit: overrides?.ethDeposit ?? defaults.ethDeposit,
|
|
166
|
+
instantLoans: overrides?.instantLoans ?? defaults.instantLoans
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function validateCanisterIdOverrides(overrides) {
|
|
170
|
+
if (!overrides) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
for (const key of Object.keys(overrides)) {
|
|
174
|
+
if (!SUPPORTED_CANISTER_ID_OVERRIDE_KEYS.has(key)) {
|
|
175
|
+
throw new LiquidiumError(
|
|
176
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
177
|
+
`Unsupported canisterIds override: ${key}`
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (!overrides.pools) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
for (const key of Object.keys(overrides.pools)) {
|
|
185
|
+
if (!SUPPORTED_POOL_CANISTER_ID_OVERRIDE_KEYS.has(key)) {
|
|
186
|
+
throw new LiquidiumError(
|
|
187
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
188
|
+
`Unsupported canisterIds.pools override: ${key}`
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
194
|
+
var CK_CANISTER_IDS = {
|
|
195
|
+
BTC: {
|
|
196
|
+
minter: "mqygn-kiaaa-aaaar-qaadq-cai",
|
|
197
|
+
ledger: "mxzaz-hqaaa-aaaar-qaada-cai"},
|
|
198
|
+
USDT: {
|
|
199
|
+
ledger: "cngnf-vqaaa-aaaar-qag4q-cai"},
|
|
200
|
+
USDC: {
|
|
201
|
+
ledger: "xevnm-gaaaa-aaaar-qafnq-cai"},
|
|
202
|
+
ICP: {
|
|
203
|
+
ledger: "ryjl3-tyaaa-aaaaa-aaaba-cai"}
|
|
204
|
+
};
|
|
205
|
+
|
|
133
206
|
// src/core/transports/api-client.ts
|
|
134
207
|
var DOM_EXCEPTION_ABORT_ERROR_NAME = "AbortError";
|
|
135
208
|
var HTTP_HEADER_CONTENT_TYPE = "content-type";
|
|
@@ -983,9 +1056,6 @@ function getVariantKey(variant) {
|
|
|
983
1056
|
}
|
|
984
1057
|
|
|
985
1058
|
// src/core/wallet-actions.ts
|
|
986
|
-
var TransferMode = {
|
|
987
|
-
native: "native"
|
|
988
|
-
};
|
|
989
1059
|
var WalletExecutionKind = {
|
|
990
1060
|
signMessage: "sign-message"
|
|
991
1061
|
};
|
|
@@ -1016,8 +1086,7 @@ function executeWith(options) {
|
|
|
1016
1086
|
chain: options.chain,
|
|
1017
1087
|
message: action.message,
|
|
1018
1088
|
account: options.account ?? action.account,
|
|
1019
|
-
actionType: action.actionType
|
|
1020
|
-
transferMode: action.transferMode
|
|
1089
|
+
actionType: action.actionType
|
|
1021
1090
|
});
|
|
1022
1091
|
return action.submit({
|
|
1023
1092
|
signature,
|
|
@@ -1240,7 +1309,6 @@ var AccountsModule = class {
|
|
|
1240
1309
|
kind: WalletActionKind.createAccount,
|
|
1241
1310
|
executionKind: WalletExecutionKind.signMessage,
|
|
1242
1311
|
actionType: WalletActionKind.createAccount,
|
|
1243
|
-
transferMode: TransferMode.native,
|
|
1244
1312
|
account: normalizedAccount,
|
|
1245
1313
|
message: createInitializeAccountMessage(expiryTimestamp, nonce),
|
|
1246
1314
|
data: {
|
|
@@ -1331,8 +1399,8 @@ function mapCanisterWalletToWallet(canisterWallet) {
|
|
|
1331
1399
|
);
|
|
1332
1400
|
}
|
|
1333
1401
|
}
|
|
1334
|
-
var KNOWN_ASSET_TAGS = ["BTC", "USDC", "USDT"];
|
|
1335
|
-
var KNOWN_CHAIN_TAGS = ["BTC", "ETH"];
|
|
1402
|
+
var KNOWN_ASSET_TAGS = ["BTC", "ICP", "USDC", "USDT"];
|
|
1403
|
+
var KNOWN_CHAIN_TAGS = ["BTC", "ETH", "ICP"];
|
|
1336
1404
|
function extractVariantTag(variant, knownTags) {
|
|
1337
1405
|
const [key] = Object.keys(variant);
|
|
1338
1406
|
if (!key) {
|
|
@@ -1911,17 +1979,14 @@ function mapInstantLoanLookupError(error) {
|
|
|
1911
1979
|
}
|
|
1912
1980
|
function mapActivity(wire) {
|
|
1913
1981
|
const amount = parseBigInt(wire.amount, "activity amount");
|
|
1914
|
-
const activityBase = {
|
|
1915
|
-
id: wire.id,
|
|
1916
|
-
poolId: wire.poolId,
|
|
1917
|
-
asset: wire.asset,
|
|
1918
|
-
chain: wire.chain,
|
|
1919
|
-
amount,
|
|
1920
|
-
timestampMs: wire.timestampMs
|
|
1921
|
-
};
|
|
1922
1982
|
if (isInflowOperation(wire.status.operation)) {
|
|
1923
1983
|
const activity = {
|
|
1924
|
-
|
|
1984
|
+
id: wire.id,
|
|
1985
|
+
poolId: wire.poolId,
|
|
1986
|
+
asset: wire.asset,
|
|
1987
|
+
chain: wire.chain,
|
|
1988
|
+
amount,
|
|
1989
|
+
timestampMs: wire.timestampMs,
|
|
1925
1990
|
status: wire.status
|
|
1926
1991
|
};
|
|
1927
1992
|
if (wire.txids) {
|
|
@@ -1934,7 +1999,12 @@ function mapActivity(wire) {
|
|
|
1934
1999
|
}
|
|
1935
2000
|
if (isOutflowOperation(wire.status.operation)) {
|
|
1936
2001
|
const activity = {
|
|
1937
|
-
|
|
2002
|
+
id: wire.id,
|
|
2003
|
+
poolId: wire.poolId,
|
|
2004
|
+
asset: wire.asset,
|
|
2005
|
+
chain: wire.chain,
|
|
2006
|
+
amount,
|
|
2007
|
+
timestampMs: wire.timestampMs,
|
|
1938
2008
|
status: wire.status
|
|
1939
2009
|
};
|
|
1940
2010
|
if (wire.txids) {
|
|
@@ -2110,6 +2180,72 @@ function validateHistoryStateFilter(state) {
|
|
|
2110
2180
|
);
|
|
2111
2181
|
}
|
|
2112
2182
|
}
|
|
2183
|
+
var LiquidiumAccountType = {
|
|
2184
|
+
ChainAddress: "ChainAddress",
|
|
2185
|
+
IcPrincipal: "IcPrincipal",
|
|
2186
|
+
IcpAccountIdentifier: "IcpAccountIdentifier",
|
|
2187
|
+
IcrcAccount: "IcrcAccount"
|
|
2188
|
+
};
|
|
2189
|
+
function createIcrcAccount(params) {
|
|
2190
|
+
return {
|
|
2191
|
+
type: "IcrcAccount",
|
|
2192
|
+
owner: params.owner.toText(),
|
|
2193
|
+
subaccount: params.subaccount,
|
|
2194
|
+
address: icrc.encodeIcrcAccount({
|
|
2195
|
+
owner: params.owner,
|
|
2196
|
+
subaccount: params.subaccount
|
|
2197
|
+
})
|
|
2198
|
+
};
|
|
2199
|
+
}
|
|
2200
|
+
function mapCanisterAccountToLiquidiumAccount(account) {
|
|
2201
|
+
if ("Native" in account) {
|
|
2202
|
+
return { type: "IcPrincipal", address: account.Native.toText() };
|
|
2203
|
+
}
|
|
2204
|
+
if ("AccountIdentifier" in account) {
|
|
2205
|
+
return {
|
|
2206
|
+
type: "IcpAccountIdentifier",
|
|
2207
|
+
address: account.AccountIdentifier
|
|
2208
|
+
};
|
|
2209
|
+
}
|
|
2210
|
+
if ("Icrc" in account) {
|
|
2211
|
+
const subaccount = normalizeOptionalSubaccount(account.Icrc.subaccount[0]);
|
|
2212
|
+
return {
|
|
2213
|
+
type: "IcrcAccount",
|
|
2214
|
+
owner: account.Icrc.owner.toText(),
|
|
2215
|
+
subaccount,
|
|
2216
|
+
address: icrc.encodeIcrcAccount({
|
|
2217
|
+
owner: account.Icrc.owner,
|
|
2218
|
+
subaccount
|
|
2219
|
+
})
|
|
2220
|
+
};
|
|
2221
|
+
}
|
|
2222
|
+
return { type: "ChainAddress", address: account.External };
|
|
2223
|
+
}
|
|
2224
|
+
function decodeIcrcAccountAddress(address) {
|
|
2225
|
+
const decoded = icrc.decodeIcrcAccount(address);
|
|
2226
|
+
const owner = principal.Principal.fromText(decoded.owner.toText());
|
|
2227
|
+
const subaccount = decoded.subaccount ? Uint8Array.from(decoded.subaccount) : void 0;
|
|
2228
|
+
return {
|
|
2229
|
+
owner,
|
|
2230
|
+
subaccount,
|
|
2231
|
+
account: createIcrcAccount({ owner, subaccount })
|
|
2232
|
+
};
|
|
2233
|
+
}
|
|
2234
|
+
function encodeIcpAccountIdentifier(params) {
|
|
2235
|
+
return icp.AccountIdentifier.fromPrincipal({
|
|
2236
|
+
principal: params.owner,
|
|
2237
|
+
subAccount: params.subaccount ? icp.SubAccount.fromBytes(params.subaccount) : void 0
|
|
2238
|
+
}).toHex();
|
|
2239
|
+
}
|
|
2240
|
+
function normalizeIcpAccountIdentifier(address) {
|
|
2241
|
+
return icp.AccountIdentifier.fromHex(address).toHex();
|
|
2242
|
+
}
|
|
2243
|
+
function normalizeOptionalSubaccount(subaccount) {
|
|
2244
|
+
if (!subaccount) {
|
|
2245
|
+
return void 0;
|
|
2246
|
+
}
|
|
2247
|
+
return subaccount instanceof Uint8Array ? subaccount : Uint8Array.from(subaccount);
|
|
2248
|
+
}
|
|
2113
2249
|
|
|
2114
2250
|
// src/core/status.ts
|
|
2115
2251
|
function createLiquidiumStatus(params) {
|
|
@@ -2159,6 +2295,7 @@ function throwInvalidApiResponseField(field) {
|
|
|
2159
2295
|
// src/core/utils/asset-decimals.ts
|
|
2160
2296
|
var ASSET_NATIVE_DECIMALS = {
|
|
2161
2297
|
BTC: 8n,
|
|
2298
|
+
ICP: 8n,
|
|
2162
2299
|
USDC: 6n,
|
|
2163
2300
|
USDT: 6n,
|
|
2164
2301
|
SOL: 9n
|
|
@@ -2554,7 +2691,7 @@ var idlFactory2 = ({ IDL }) => {
|
|
|
2554
2691
|
|
|
2555
2692
|
// src/core/canisters/ckbtc/minter.ts
|
|
2556
2693
|
function createCkBtcMinterActor(canisterContext) {
|
|
2557
|
-
const canisterId = CK_CANISTER_IDS.
|
|
2694
|
+
const canisterId = CK_CANISTER_IDS.BTC.minter;
|
|
2558
2695
|
return agent.Actor.createActor(idlFactory2, {
|
|
2559
2696
|
agent: canisterContext.agent,
|
|
2560
2697
|
canisterId
|
|
@@ -3005,55 +3142,43 @@ var EvmSupplyApprovalStrategy = {
|
|
|
3005
3142
|
};
|
|
3006
3143
|
|
|
3007
3144
|
// src/modules/lending/_internal/supply-targets.ts
|
|
3008
|
-
async function
|
|
3009
|
-
const
|
|
3010
|
-
|
|
3011
|
-
|
|
3145
|
+
async function resolveSupplyTargetForPool(canisterContext, request, selectedPool) {
|
|
3146
|
+
const identifier = resolveSupplyAssetIdentifier({
|
|
3147
|
+
asset: selectedPool.asset,
|
|
3148
|
+
poolChain: selectedPool.chain,
|
|
3149
|
+
transferChain: request.chain ?? selectedPool.chain
|
|
3150
|
+
});
|
|
3012
3151
|
const mechanism = resolveSupplyMechanism({
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
requestedMechanism: request.mechanism
|
|
3152
|
+
identifier,
|
|
3153
|
+
mechanism: request.mechanism
|
|
3016
3154
|
});
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
asset,
|
|
3025
|
-
chain,
|
|
3026
|
-
action: request.action
|
|
3027
|
-
}
|
|
3028
|
-
);
|
|
3029
|
-
case SupplyPlanType.contractInteraction:
|
|
3030
|
-
return getIcrcAccountSupplyTarget(request.profileId, {
|
|
3031
|
-
poolId: request.poolId,
|
|
3032
|
-
asset,
|
|
3033
|
-
chain,
|
|
3034
|
-
action: request.action
|
|
3035
|
-
});
|
|
3155
|
+
const targetRequest = {
|
|
3156
|
+
...identifier,
|
|
3157
|
+
poolId: request.poolId,
|
|
3158
|
+
action: request.action
|
|
3159
|
+
};
|
|
3160
|
+
if (mechanism === SupplyPlanType.contractInteraction) {
|
|
3161
|
+
return getIcrcAccountSupplyTarget(request.profileId, targetRequest);
|
|
3036
3162
|
}
|
|
3163
|
+
if (identifier.chain === Chain.ICP) {
|
|
3164
|
+
return identifier.asset === Asset.ICP ? getIcpLedgerSupplyTarget(request.profileId, targetRequest) : getIcrcAccountSupplyTarget(request.profileId, targetRequest);
|
|
3165
|
+
}
|
|
3166
|
+
return await getChainAddressSupplyTarget(
|
|
3167
|
+
canisterContext,
|
|
3168
|
+
request.profileId,
|
|
3169
|
+
targetRequest
|
|
3170
|
+
);
|
|
3037
3171
|
}
|
|
3038
3172
|
function resolveSupplyMechanism(params) {
|
|
3039
|
-
if (params.
|
|
3040
|
-
if (params.requestedMechanism === SupplyPlanType.contractInteraction) {
|
|
3041
|
-
throw new LiquidiumError(
|
|
3042
|
-
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
3043
|
-
"Contract-interaction supply is not supported for BTC on BTC"
|
|
3044
|
-
);
|
|
3045
|
-
}
|
|
3173
|
+
if (params.mechanism !== SupplyPlanType.contractInteraction) {
|
|
3046
3174
|
return SupplyPlanType.transfer;
|
|
3047
3175
|
}
|
|
3048
|
-
if (
|
|
3049
|
-
|
|
3050
|
-
return params.requestedMechanism;
|
|
3051
|
-
}
|
|
3052
|
-
return SupplyPlanType.transfer;
|
|
3176
|
+
if (params.identifier.chain === Chain.ETH && (params.identifier.asset === Asset.USDC || params.identifier.asset === Asset.USDT)) {
|
|
3177
|
+
return SupplyPlanType.contractInteraction;
|
|
3053
3178
|
}
|
|
3054
3179
|
throw new LiquidiumError(
|
|
3055
3180
|
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
3056
|
-
`
|
|
3181
|
+
`Contract-interaction supply is not supported for ${params.identifier.asset} on ${params.identifier.chain}`
|
|
3057
3182
|
);
|
|
3058
3183
|
}
|
|
3059
3184
|
function isEthStablecoin(asset, chain) {
|
|
@@ -3125,9 +3250,33 @@ async function getPoolById(canisterContext, poolId) {
|
|
|
3125
3250
|
}
|
|
3126
3251
|
return decodedPool;
|
|
3127
3252
|
}
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3253
|
+
function resolveSupplyAssetIdentifier(params) {
|
|
3254
|
+
if (params.asset === Asset.BTC && params.poolChain === Chain.BTC) {
|
|
3255
|
+
if (params.transferChain === Chain.BTC) {
|
|
3256
|
+
return { asset: Asset.BTC, chain: Chain.BTC };
|
|
3257
|
+
}
|
|
3258
|
+
if (params.transferChain === Chain.ICP) {
|
|
3259
|
+
return { asset: Asset.BTC, chain: Chain.ICP };
|
|
3260
|
+
}
|
|
3261
|
+
}
|
|
3262
|
+
if ((params.asset === Asset.USDC || params.asset === Asset.USDT) && params.poolChain === Chain.ETH) {
|
|
3263
|
+
if (params.transferChain === Chain.ETH) {
|
|
3264
|
+
return { asset: params.asset, chain: Chain.ETH };
|
|
3265
|
+
}
|
|
3266
|
+
if (params.transferChain === Chain.ICP) {
|
|
3267
|
+
return { asset: params.asset, chain: Chain.ICP };
|
|
3268
|
+
}
|
|
3269
|
+
}
|
|
3270
|
+
if (params.asset === Asset.ICP && params.poolChain === Chain.ICP && params.transferChain === Chain.ICP) {
|
|
3271
|
+
return { asset: Asset.ICP, chain: Chain.ICP };
|
|
3272
|
+
}
|
|
3273
|
+
throw new LiquidiumError(
|
|
3274
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
3275
|
+
`Supply is not supported for ${params.asset} pool on ${params.poolChain} using ${params.transferChain}`
|
|
3276
|
+
);
|
|
3277
|
+
}
|
|
3278
|
+
async function getChainAddressSupplyTarget(canisterContext, profileId, request) {
|
|
3279
|
+
if (request.chain === Chain.ETH) {
|
|
3131
3280
|
const tokenAddress = getEthStablecoinContractAddress(request.asset);
|
|
3132
3281
|
const subaccount2 = encodeInflowSubaccount({
|
|
3133
3282
|
action: request.action,
|
|
@@ -3146,7 +3295,6 @@ async function getNativeAddressSupplyTarget(canisterContext, profileId, request)
|
|
|
3146
3295
|
throw mapDepositAccountErrorToLiquidiumError(result.Err);
|
|
3147
3296
|
}
|
|
3148
3297
|
return {
|
|
3149
|
-
type: "nativeAddress",
|
|
3150
3298
|
poolId: request.poolId,
|
|
3151
3299
|
asset: request.asset,
|
|
3152
3300
|
chain: request.chain,
|
|
@@ -3154,11 +3302,11 @@ async function getNativeAddressSupplyTarget(canisterContext, profileId, request)
|
|
|
3154
3302
|
address: result.Ok
|
|
3155
3303
|
};
|
|
3156
3304
|
}
|
|
3157
|
-
const configuredBtcPoolId = canisterContext.canisterIds.
|
|
3305
|
+
const configuredBtcPoolId = canisterContext.canisterIds.pools.btc;
|
|
3158
3306
|
if (request.poolId !== configuredBtcPoolId) {
|
|
3159
3307
|
throw new LiquidiumError(
|
|
3160
3308
|
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
3161
|
-
`
|
|
3309
|
+
`Chain-address BTC inflow targets require the configured BTC pool ${configuredBtcPoolId}, received ${request.poolId}`
|
|
3162
3310
|
);
|
|
3163
3311
|
}
|
|
3164
3312
|
const subaccount = encodeInflowSubaccount({
|
|
@@ -3171,56 +3319,42 @@ async function getNativeAddressSupplyTarget(canisterContext, profileId, request)
|
|
|
3171
3319
|
subaccount: [subaccount]
|
|
3172
3320
|
}
|
|
3173
3321
|
);
|
|
3174
|
-
return {
|
|
3175
|
-
type: "nativeAddress",
|
|
3176
|
-
poolId: request.poolId,
|
|
3177
|
-
asset: request.asset,
|
|
3178
|
-
chain: request.chain,
|
|
3179
|
-
action: request.action,
|
|
3180
|
-
address
|
|
3181
|
-
};
|
|
3322
|
+
return { ...request, address };
|
|
3182
3323
|
}
|
|
3183
3324
|
function getIcrcAccountSupplyTarget(profileId, request) {
|
|
3184
|
-
|
|
3325
|
+
const account = createInflowIcrcAccount(profileId, request);
|
|
3326
|
+
return { ...request, address: account.address };
|
|
3327
|
+
}
|
|
3328
|
+
function getIcpLedgerSupplyTarget(profileId, request) {
|
|
3185
3329
|
const poolPrincipal = principal.Principal.fromText(request.poolId);
|
|
3186
3330
|
const subaccount = encodeInflowSubaccount({
|
|
3187
3331
|
action: request.action,
|
|
3188
3332
|
principal: principal.Principal.fromText(profileId)
|
|
3189
3333
|
});
|
|
3334
|
+
const account = createIcrcAccount({
|
|
3335
|
+
owner: poolPrincipal,
|
|
3336
|
+
subaccount
|
|
3337
|
+
});
|
|
3190
3338
|
return {
|
|
3191
|
-
type: "icrcAccount",
|
|
3192
3339
|
poolId: request.poolId,
|
|
3193
|
-
asset:
|
|
3194
|
-
chain:
|
|
3340
|
+
asset: Asset.ICP,
|
|
3341
|
+
chain: Chain.ICP,
|
|
3195
3342
|
action: request.action,
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
account: icrc.encodeIcrcAccount({
|
|
3343
|
+
address: account.address,
|
|
3344
|
+
icpAccountIdentifier: encodeIcpAccountIdentifier({
|
|
3199
3345
|
owner: poolPrincipal,
|
|
3200
3346
|
subaccount
|
|
3201
3347
|
})
|
|
3202
3348
|
};
|
|
3203
3349
|
}
|
|
3204
|
-
function
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
3213
|
-
`Native address inflow targets are not supported for ${asset} on ${chain}`
|
|
3214
|
-
);
|
|
3215
|
-
}
|
|
3216
|
-
function assertSupportsIcrcAccountInflowTarget(asset) {
|
|
3217
|
-
if (asset === Asset.BTC || asset === Asset.USDT || asset === Asset.USDC) {
|
|
3218
|
-
return;
|
|
3219
|
-
}
|
|
3220
|
-
throw new LiquidiumError(
|
|
3221
|
-
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
3222
|
-
`ICRC account inflow targets are not supported for ${asset}`
|
|
3223
|
-
);
|
|
3350
|
+
function createInflowIcrcAccount(profileId, request) {
|
|
3351
|
+
return createIcrcAccount({
|
|
3352
|
+
owner: principal.Principal.fromText(request.poolId),
|
|
3353
|
+
subaccount: encodeInflowSubaccount({
|
|
3354
|
+
action: request.action,
|
|
3355
|
+
principal: principal.Principal.fromText(profileId)
|
|
3356
|
+
})
|
|
3357
|
+
});
|
|
3224
3358
|
}
|
|
3225
3359
|
|
|
3226
3360
|
// src/core/borrow-minimums.ts
|
|
@@ -3694,25 +3828,20 @@ function isEthStablecoin2(asset) {
|
|
|
3694
3828
|
}
|
|
3695
3829
|
|
|
3696
3830
|
// src/modules/instant-loans/_internal/address-validation.ts
|
|
3697
|
-
function validateInstantLoanBorrowDestination(address, asset) {
|
|
3831
|
+
function validateInstantLoanBorrowDestination(address, asset, chain) {
|
|
3698
3832
|
return normalizeExternalAddress({
|
|
3699
3833
|
address,
|
|
3700
3834
|
asset,
|
|
3701
|
-
chain
|
|
3835
|
+
chain
|
|
3702
3836
|
});
|
|
3703
3837
|
}
|
|
3704
|
-
function validateInstantLoanRefundDestination(address, asset) {
|
|
3838
|
+
function validateInstantLoanRefundDestination(address, asset, chain) {
|
|
3705
3839
|
return normalizeExternalAddress({
|
|
3706
3840
|
address,
|
|
3707
3841
|
asset,
|
|
3708
|
-
chain
|
|
3842
|
+
chain
|
|
3709
3843
|
});
|
|
3710
3844
|
}
|
|
3711
|
-
function getChainForInstantLoanAsset(asset) {
|
|
3712
|
-
if (asset === Asset.BTC) return Chain.BTC;
|
|
3713
|
-
if (asset === Asset.USDC || asset === Asset.USDT) return Chain.ETH;
|
|
3714
|
-
return asset;
|
|
3715
|
-
}
|
|
3716
3845
|
|
|
3717
3846
|
// src/modules/instant-loans/instant-loans.ts
|
|
3718
3847
|
var REPAYMENT_BUFFER_SECONDS = 86400n;
|
|
@@ -3725,10 +3854,32 @@ var INSTANT_LOAN_FIND_QUERY_MAX_LENGTH = 256;
|
|
|
3725
3854
|
var INSTANT_LOAN_WIRE_CONTEXT = "instant loan";
|
|
3726
3855
|
var INSTANT_LOAN_ASSETS = [
|
|
3727
3856
|
Asset.BTC,
|
|
3728
|
-
Asset.
|
|
3857
|
+
Asset.ICP,
|
|
3729
3858
|
Asset.USDC,
|
|
3730
3859
|
Asset.USDT
|
|
3731
3860
|
];
|
|
3861
|
+
var INSTANT_LOAN_CHAINS = [
|
|
3862
|
+
Chain.BTC,
|
|
3863
|
+
Chain.ETH,
|
|
3864
|
+
Chain.ICP
|
|
3865
|
+
];
|
|
3866
|
+
var ICP_ACCOUNT_IDENTIFIER_HEX_LENGTH = 64;
|
|
3867
|
+
var InstantLoanCreatedError = class extends Error {
|
|
3868
|
+
code = "INSTANT_LOAN_HYDRATION_FAILED";
|
|
3869
|
+
loanId;
|
|
3870
|
+
ref;
|
|
3871
|
+
cause;
|
|
3872
|
+
constructor(loanId, cause) {
|
|
3873
|
+
const ref = publicIdFromInt(loanId);
|
|
3874
|
+
super(
|
|
3875
|
+
`Instant loan ${ref} was created, but its enriched state could not be loaded`
|
|
3876
|
+
);
|
|
3877
|
+
this.name = "InstantLoanCreatedError";
|
|
3878
|
+
this.loanId = loanId;
|
|
3879
|
+
this.ref = ref;
|
|
3880
|
+
this.cause = cause;
|
|
3881
|
+
}
|
|
3882
|
+
};
|
|
3732
3883
|
var InstantLoansModule = class {
|
|
3733
3884
|
constructor(canisterContext, apiClient, activities, lending, positions) {
|
|
3734
3885
|
this.canisterContext = canisterContext;
|
|
@@ -3751,37 +3902,39 @@ var InstantLoansModule = class {
|
|
|
3751
3902
|
* selected pool decimals, and call `client.quote.calculateLtv(...)` before
|
|
3752
3903
|
* creation to block invalid LTV input.
|
|
3753
3904
|
*
|
|
3754
|
-
* `
|
|
3755
|
-
* `
|
|
3905
|
+
* `borrow.destination` receives the borrowed asset after the loan starts.
|
|
3906
|
+
* `refund.destination` receives collateral refunds or withdrawals. Use
|
|
3756
3907
|
* `depositWindowSeconds` for the user-facing collateral deposit timeout; the
|
|
3757
3908
|
* SDK maps it to the canister's internal `ltv_timer_s` field.
|
|
3758
3909
|
*
|
|
3759
|
-
* @param request -
|
|
3910
|
+
* @param request - Collateral, borrow, refund, LTV limit, timeout, and inflow options.
|
|
3760
3911
|
* @returns Hydrated loan state plus generated initial-deposit and repayment quote targets.
|
|
3761
3912
|
*/
|
|
3762
3913
|
async create(request) {
|
|
3763
3914
|
validateCreateRequest(request);
|
|
3764
|
-
const borrowDestination = {
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3915
|
+
const borrowDestination = resolveInstantLoanDestination({
|
|
3916
|
+
destination: request.borrow.destination,
|
|
3917
|
+
asset: request.borrow.asset,
|
|
3918
|
+
role: "borrow",
|
|
3919
|
+
chain: request.borrow.chain,
|
|
3920
|
+
normalizeExternalDestination: validateInstantLoanBorrowDestination
|
|
3921
|
+
});
|
|
3922
|
+
const refundDestination = resolveInstantLoanDestination({
|
|
3923
|
+
destination: request.refund.destination,
|
|
3924
|
+
asset: request.collateral.asset,
|
|
3925
|
+
role: "refund",
|
|
3926
|
+
chain: request.refund.chain,
|
|
3927
|
+
normalizeExternalDestination: validateInstantLoanRefundDestination
|
|
3928
|
+
});
|
|
3776
3929
|
const apiClient = this.requireApi("Instant loan creation");
|
|
3777
3930
|
await this.validateInstantLoanLtvPolicy(request);
|
|
3778
3931
|
const response = await apiClient.post(SdkApiPath.instantLoans, {
|
|
3779
|
-
collateralPoolId: request.
|
|
3780
|
-
borrowPoolId: request.
|
|
3781
|
-
collateralAsset: request.
|
|
3782
|
-
borrowAsset: request.
|
|
3783
|
-
collateralAmount: request.
|
|
3784
|
-
borrowAmount: request.
|
|
3932
|
+
collateralPoolId: request.collateral.poolId,
|
|
3933
|
+
borrowPoolId: request.borrow.poolId,
|
|
3934
|
+
collateralAsset: request.collateral.asset,
|
|
3935
|
+
borrowAsset: request.borrow.asset,
|
|
3936
|
+
collateralAmount: request.collateral.amount.toString(),
|
|
3937
|
+
borrowAmount: request.borrow.amount.toString(),
|
|
3785
3938
|
ltvMaxBps: request.ltvMaxBps.toString(),
|
|
3786
3939
|
depositWindowSeconds: request.depositWindowSeconds.toString(),
|
|
3787
3940
|
borrowDestination,
|
|
@@ -3791,15 +3944,21 @@ var InstantLoansModule = class {
|
|
|
3791
3944
|
context: INSTANT_LOAN_WIRE_CONTEXT,
|
|
3792
3945
|
label: "loan ID"
|
|
3793
3946
|
});
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3947
|
+
try {
|
|
3948
|
+
const collateralAmount = parseUnsignedApiBigint(
|
|
3949
|
+
response.loan.collateral.amountHint,
|
|
3950
|
+
{
|
|
3951
|
+
context: INSTANT_LOAN_WIRE_CONTEXT,
|
|
3952
|
+
label: "collateral amount"
|
|
3953
|
+
}
|
|
3954
|
+
);
|
|
3955
|
+
const record = await this.getLoanRecord(loanId);
|
|
3956
|
+
return await this.mapLoanRecord(record, collateralAmount, {
|
|
3957
|
+
borrowChain: request.borrow.chain
|
|
3958
|
+
});
|
|
3959
|
+
} catch (cause) {
|
|
3960
|
+
throw new InstantLoanCreatedError(loanId, cause);
|
|
3961
|
+
}
|
|
3803
3962
|
}
|
|
3804
3963
|
/**
|
|
3805
3964
|
* Resolves canonical canister state by loan id or short reference.
|
|
@@ -3965,7 +4124,16 @@ var InstantLoansModule = class {
|
|
|
3965
4124
|
throw mapCanisterCallErrorToLiquidiumError("get_loan", error);
|
|
3966
4125
|
}
|
|
3967
4126
|
}
|
|
3968
|
-
async mapLoanRecord(record, collateralAmount) {
|
|
4127
|
+
async mapLoanRecord(record, collateralAmount, chainOptions = {}) {
|
|
4128
|
+
const borrowDestination = accountFromCanister(record.borrow_destination);
|
|
4129
|
+
const collateralAsset = parseInstantLoanAsset(
|
|
4130
|
+
record.lend_asset,
|
|
4131
|
+
"collateral asset"
|
|
4132
|
+
);
|
|
4133
|
+
const borrowAsset = parseInstantLoanAsset(
|
|
4134
|
+
record.borrow_asset,
|
|
4135
|
+
"borrow asset"
|
|
4136
|
+
);
|
|
3969
4137
|
return await this.hydrateLoan({
|
|
3970
4138
|
loanId: record.id,
|
|
3971
4139
|
profileId: record.lending_profile.toText(),
|
|
@@ -3974,17 +4142,18 @@ var InstantLoansModule = class {
|
|
|
3974
4142
|
collateralPoolId: record.lend_pool_id.toText(),
|
|
3975
4143
|
collateralAmount,
|
|
3976
4144
|
borrowPoolId: record.borrow_pool_id.toText(),
|
|
3977
|
-
collateralAsset
|
|
3978
|
-
borrowAsset
|
|
4145
|
+
collateralAsset,
|
|
4146
|
+
borrowAsset,
|
|
3979
4147
|
borrowAmount: record.borrow_amount,
|
|
3980
|
-
borrowDestination
|
|
4148
|
+
borrowDestination,
|
|
3981
4149
|
refundDestination: accountFromCanister(record.refund_destination),
|
|
3982
4150
|
started: record.started,
|
|
3983
4151
|
depositDetectedTimestamp: record.deposit_detected_ts[0] ?? null,
|
|
3984
4152
|
expiryTimestamp: record.expires_at[0] ?? deriveDepositExpiryTimestamp({
|
|
3985
4153
|
depositDetectedTimestamp: record.deposit_detected_ts[0] ?? null,
|
|
3986
4154
|
depositWindowSeconds: record.ltv_timer_s
|
|
3987
|
-
})
|
|
4155
|
+
}),
|
|
4156
|
+
borrowChain: chainOptions.borrowChain ?? inferInstantLoanDeliveryChain(borrowDestination, borrowAsset)
|
|
3988
4157
|
});
|
|
3989
4158
|
}
|
|
3990
4159
|
async getCollateralAmountHint(loanId) {
|
|
@@ -4004,24 +4173,22 @@ var InstantLoansModule = class {
|
|
|
4004
4173
|
const collateralAsset = input.collateralAsset;
|
|
4005
4174
|
const borrowAsset = input.borrowAsset;
|
|
4006
4175
|
const [
|
|
4007
|
-
|
|
4008
|
-
|
|
4176
|
+
depositTargetSet,
|
|
4177
|
+
repaymentTargetSet,
|
|
4009
4178
|
collateralPosition,
|
|
4010
4179
|
borrowPosition,
|
|
4011
4180
|
borrowPoolRate,
|
|
4012
4181
|
activeActivities
|
|
4013
4182
|
] = await Promise.all([
|
|
4014
|
-
|
|
4183
|
+
this.resolveInstantLoanInflowTargets({
|
|
4015
4184
|
profileId,
|
|
4016
4185
|
poolId: collateralPoolId,
|
|
4017
|
-
action: SupplyAction.deposit
|
|
4018
|
-
mechanism: SupplyPlanType.transfer
|
|
4186
|
+
action: SupplyAction.deposit
|
|
4019
4187
|
}),
|
|
4020
|
-
|
|
4188
|
+
this.resolveInstantLoanInflowTargets({
|
|
4021
4189
|
profileId,
|
|
4022
4190
|
poolId: borrowPoolId,
|
|
4023
|
-
action: SupplyAction.repayment
|
|
4024
|
-
mechanism: SupplyPlanType.transfer
|
|
4191
|
+
action: SupplyAction.repayment
|
|
4025
4192
|
}),
|
|
4026
4193
|
this.positions.getPosition(profileId, collateralPoolId),
|
|
4027
4194
|
this.positions.getPosition(profileId, borrowPoolId),
|
|
@@ -4033,8 +4200,6 @@ var InstantLoansModule = class {
|
|
|
4033
4200
|
borrowPosition,
|
|
4034
4201
|
borrowPoolRate.borrowRate
|
|
4035
4202
|
);
|
|
4036
|
-
const repaymentInflowFee = totalDebtAmount > 0n ? await this.estimateRepaymentInflowFee(borrowAsset, repayTarget.chain) : { totalFee: 0n, estimateAvailable: false };
|
|
4037
|
-
const repaymentAmount = totalDebtAmount + interestBufferAmount + repaymentInflowFee.totalFee;
|
|
4038
4203
|
const currentCollateralAmount = collateralPosition?.deposited ?? 0n;
|
|
4039
4204
|
const collateralAmount = input.collateralAmount;
|
|
4040
4205
|
const collateralDecimals = collateralPosition?.depositedDecimals ?? getAssetNativeDecimals(collateralAsset);
|
|
@@ -4054,22 +4219,28 @@ var InstantLoansModule = class {
|
|
|
4054
4219
|
collateralAmount,
|
|
4055
4220
|
decimals: collateralDecimals,
|
|
4056
4221
|
asset: collateralAsset,
|
|
4057
|
-
|
|
4222
|
+
targets: depositTargetSet.targets,
|
|
4058
4223
|
detectedTimestamp: input.depositDetectedTimestamp,
|
|
4059
4224
|
expiryTimestamp: input.expiryTimestamp
|
|
4060
4225
|
});
|
|
4226
|
+
const repaymentTargets = await this.createRepaymentTargetQuotes({
|
|
4227
|
+
baseRepaymentAmount: totalDebtAmount + interestBufferAmount,
|
|
4228
|
+
asset: borrowAsset,
|
|
4229
|
+
targets: repaymentTargetSet.targets
|
|
4230
|
+
});
|
|
4061
4231
|
const repayment = {
|
|
4062
|
-
amount: repaymentAmount,
|
|
4063
4232
|
decimals: borrowedDecimals,
|
|
4064
4233
|
debtAmount: totalDebtAmount,
|
|
4065
4234
|
interestBufferAmount,
|
|
4066
4235
|
interestBufferSeconds: REPAYMENT_BUFFER_SECONDS,
|
|
4067
|
-
inflowFeeAmount: repaymentInflowFee.totalFee,
|
|
4068
|
-
inflowFeeEstimateAvailable: repaymentInflowFee.estimateAvailable,
|
|
4069
4236
|
asset: borrowAsset,
|
|
4070
|
-
|
|
4071
|
-
target: repayTarget
|
|
4237
|
+
targets: repaymentTargets
|
|
4072
4238
|
};
|
|
4239
|
+
const borrowIdentifier = getInstantLoanAssetIdentifier(
|
|
4240
|
+
borrowAsset,
|
|
4241
|
+
input.borrowChain,
|
|
4242
|
+
"borrow"
|
|
4243
|
+
);
|
|
4073
4244
|
return {
|
|
4074
4245
|
loanId: input.loanId,
|
|
4075
4246
|
ref: publicIdFromInt(input.loanId),
|
|
@@ -4080,16 +4251,14 @@ var InstantLoansModule = class {
|
|
|
4080
4251
|
depositWindowSeconds: input.depositWindowSeconds
|
|
4081
4252
|
},
|
|
4082
4253
|
collateral: {
|
|
4083
|
-
poolId: collateralPoolId,
|
|
4084
4254
|
asset: collateralAsset,
|
|
4085
|
-
|
|
4255
|
+
poolId: collateralPoolId,
|
|
4086
4256
|
decimals: collateralDecimals,
|
|
4087
4257
|
amount: collateralAmount
|
|
4088
4258
|
},
|
|
4089
4259
|
borrow: {
|
|
4260
|
+
...borrowIdentifier,
|
|
4090
4261
|
poolId: borrowPoolId,
|
|
4091
|
-
asset: borrowAsset,
|
|
4092
|
-
chain: repayTarget.chain,
|
|
4093
4262
|
decimals: borrowedDecimals,
|
|
4094
4263
|
amount: input.borrowAmount,
|
|
4095
4264
|
destination: input.borrowDestination
|
|
@@ -4109,37 +4278,86 @@ var InstantLoansModule = class {
|
|
|
4109
4278
|
};
|
|
4110
4279
|
}
|
|
4111
4280
|
async createInitialDepositQuote(input) {
|
|
4112
|
-
const
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4281
|
+
const targets = {};
|
|
4282
|
+
for (const chain of INSTANT_LOAN_CHAINS) {
|
|
4283
|
+
const target = input.targets[chain];
|
|
4284
|
+
if (!target) continue;
|
|
4285
|
+
assertTargetAsset(target, input.asset);
|
|
4286
|
+
const inflowFee = await this.lending.estimateInflowFee(target);
|
|
4287
|
+
targets[chain] = {
|
|
4288
|
+
amount: input.collateralAmount + inflowFee.totalFee,
|
|
4289
|
+
inflowFeeAmount: inflowFee.totalFee,
|
|
4290
|
+
target
|
|
4291
|
+
};
|
|
4292
|
+
}
|
|
4116
4293
|
return {
|
|
4117
|
-
amount: input.collateralAmount + inflowFee.totalFee,
|
|
4118
4294
|
decimals: input.decimals,
|
|
4119
4295
|
collateralAmount: input.collateralAmount,
|
|
4120
|
-
inflowFeeAmount: inflowFee.totalFee,
|
|
4121
4296
|
asset: input.asset,
|
|
4122
|
-
|
|
4123
|
-
target: input.target,
|
|
4297
|
+
targets,
|
|
4124
4298
|
detectedTimestamp: input.detectedTimestamp,
|
|
4125
4299
|
expiryTimestamp: input.expiryTimestamp
|
|
4126
4300
|
};
|
|
4127
4301
|
}
|
|
4128
|
-
async
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4302
|
+
async resolveInstantLoanInflowTargets(request) {
|
|
4303
|
+
const selectedPool = await getPoolById(
|
|
4304
|
+
this.canisterContext,
|
|
4305
|
+
request.poolId
|
|
4306
|
+
);
|
|
4307
|
+
const baseRequest = {
|
|
4308
|
+
profileId: request.profileId,
|
|
4309
|
+
poolId: request.poolId,
|
|
4310
|
+
action: request.action,
|
|
4311
|
+
mechanism: SupplyPlanType.transfer
|
|
4312
|
+
};
|
|
4313
|
+
const poolChainTarget = await resolveSupplyTargetForPool(
|
|
4314
|
+
this.canisterContext,
|
|
4315
|
+
baseRequest,
|
|
4316
|
+
selectedPool
|
|
4317
|
+
);
|
|
4318
|
+
const poolChain = poolChainTarget.chain;
|
|
4319
|
+
const targets = {
|
|
4320
|
+
[poolChain]: poolChainTarget
|
|
4321
|
+
};
|
|
4322
|
+
if (poolChain === Chain.ICP) {
|
|
4323
|
+
return { targets };
|
|
4324
|
+
}
|
|
4325
|
+
const icpTarget = await resolveSupplyTargetForPool(
|
|
4326
|
+
this.canisterContext,
|
|
4327
|
+
{ ...baseRequest, chain: Chain.ICP },
|
|
4328
|
+
selectedPool
|
|
4329
|
+
);
|
|
4330
|
+
targets[Chain.ICP] = icpTarget;
|
|
4331
|
+
return { targets };
|
|
4332
|
+
}
|
|
4333
|
+
async createRepaymentTargetQuotes(input) {
|
|
4334
|
+
const quotes = {};
|
|
4335
|
+
for (const chain of INSTANT_LOAN_CHAINS) {
|
|
4336
|
+
const target = input.targets[chain];
|
|
4337
|
+
if (!target) continue;
|
|
4338
|
+
assertTargetAsset(target, input.asset);
|
|
4339
|
+
const repaymentInflowFee = input.baseRepaymentAmount > 0n ? await this.estimateRepaymentInflowFee(target) : { totalFee: 0n, estimateAvailable: false };
|
|
4340
|
+
quotes[chain] = {
|
|
4341
|
+
amount: input.baseRepaymentAmount + repaymentInflowFee.totalFee,
|
|
4342
|
+
inflowFeeAmount: repaymentInflowFee.totalFee,
|
|
4343
|
+
inflowFeeEstimateAvailable: repaymentInflowFee.estimateAvailable,
|
|
4344
|
+
target
|
|
4345
|
+
};
|
|
4346
|
+
}
|
|
4347
|
+
return quotes;
|
|
4348
|
+
}
|
|
4349
|
+
async estimateRepaymentInflowFee(target) {
|
|
4350
|
+
try {
|
|
4351
|
+
const fee = await this.lending.estimateInflowFee(target);
|
|
4352
|
+
return { totalFee: fee.totalFee, estimateAvailable: true };
|
|
4353
|
+
} catch {
|
|
4354
|
+
return {
|
|
4355
|
+
totalFee: getRepaymentInflowFeeFallback(target.asset, target.chain),
|
|
4356
|
+
estimateAvailable: false
|
|
4357
|
+
};
|
|
4358
|
+
}
|
|
4359
|
+
}
|
|
4360
|
+
requireApi(action) {
|
|
4143
4361
|
if (!this.apiClient) {
|
|
4144
4362
|
throw new LiquidiumError(
|
|
4145
4363
|
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
@@ -4170,10 +4388,10 @@ var InstantLoansModule = class {
|
|
|
4170
4388
|
]);
|
|
4171
4389
|
const ltvCalculation = new QuoteModule().calculateLtv(
|
|
4172
4390
|
{
|
|
4173
|
-
borrowAmount: request.
|
|
4174
|
-
borrowPoolId: request.
|
|
4175
|
-
collateralAmount: request.
|
|
4176
|
-
collateralPoolId: request.
|
|
4391
|
+
borrowAmount: request.borrow.amount,
|
|
4392
|
+
borrowPoolId: request.borrow.poolId,
|
|
4393
|
+
collateralAmount: request.collateral.amount,
|
|
4394
|
+
collateralPoolId: request.collateral.poolId
|
|
4177
4395
|
},
|
|
4178
4396
|
pools,
|
|
4179
4397
|
assetPrices
|
|
@@ -4195,6 +4413,15 @@ function getRepaymentInflowFeeFallback(asset, chain) {
|
|
|
4195
4413
|
}
|
|
4196
4414
|
return 0n;
|
|
4197
4415
|
}
|
|
4416
|
+
function assertTargetAsset(target, expectedAsset) {
|
|
4417
|
+
if (target.asset === expectedAsset) {
|
|
4418
|
+
return;
|
|
4419
|
+
}
|
|
4420
|
+
throw new LiquidiumError(
|
|
4421
|
+
LiquidiumErrorCode.INTERNAL,
|
|
4422
|
+
`Instant loan pool target asset ${target.asset} does not match ${expectedAsset}`
|
|
4423
|
+
);
|
|
4424
|
+
}
|
|
4198
4425
|
function calculateInterestBufferAmount(borrowPosition, annualBorrowRate) {
|
|
4199
4426
|
const totalDebtAmount = calculateTotalDebtAmount(borrowPosition);
|
|
4200
4427
|
if (totalDebtAmount <= 0n || annualBorrowRate <= 0n) {
|
|
@@ -4287,13 +4514,23 @@ function deriveDepositExpiryTimestamp(input) {
|
|
|
4287
4514
|
return input.depositDetectedTimestamp + input.depositWindowSeconds;
|
|
4288
4515
|
}
|
|
4289
4516
|
function validateCreateRequest(request) {
|
|
4290
|
-
|
|
4517
|
+
getInstantLoanAssetIdentifier(
|
|
4518
|
+
request.borrow.asset,
|
|
4519
|
+
request.borrow.chain,
|
|
4520
|
+
"borrow"
|
|
4521
|
+
);
|
|
4522
|
+
getInstantLoanAssetIdentifier(
|
|
4523
|
+
request.collateral.asset,
|
|
4524
|
+
request.refund.chain,
|
|
4525
|
+
"refund"
|
|
4526
|
+
);
|
|
4527
|
+
if (request.collateral.amount <= 0n) {
|
|
4291
4528
|
throw new LiquidiumError(
|
|
4292
4529
|
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
4293
4530
|
"Instant loan collateral amount must be greater than zero"
|
|
4294
4531
|
);
|
|
4295
4532
|
}
|
|
4296
|
-
if (request.
|
|
4533
|
+
if (request.borrow.amount <= 0n) {
|
|
4297
4534
|
throw new LiquidiumError(
|
|
4298
4535
|
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
4299
4536
|
"Instant loan borrow amount must be greater than zero"
|
|
@@ -4318,45 +4555,200 @@ function throwLtvCalculationError(error) {
|
|
|
4318
4555
|
error?.message ?? "Unable to calculate instant loan LTV"
|
|
4319
4556
|
);
|
|
4320
4557
|
}
|
|
4321
|
-
function
|
|
4322
|
-
|
|
4323
|
-
|
|
4558
|
+
function inferInstantLoanDeliveryChain(destination, asset) {
|
|
4559
|
+
if (destination.type !== "ChainAddress") {
|
|
4560
|
+
return Chain.ICP;
|
|
4561
|
+
}
|
|
4562
|
+
if (asset === Asset.BTC) {
|
|
4563
|
+
return Chain.BTC;
|
|
4564
|
+
}
|
|
4565
|
+
if (asset === Asset.USDC || asset === Asset.USDT) {
|
|
4566
|
+
return Chain.ETH;
|
|
4567
|
+
}
|
|
4568
|
+
return Chain.ICP;
|
|
4569
|
+
}
|
|
4570
|
+
function resolveInstantLoanDestination(params) {
|
|
4571
|
+
getInstantLoanAssetIdentifier(params.asset, params.chain, params.role);
|
|
4572
|
+
if (typeof params.destination === "string") {
|
|
4573
|
+
return resolveInstantLoanStringDestination({
|
|
4574
|
+
destination: params.destination,
|
|
4575
|
+
asset: params.asset,
|
|
4576
|
+
role: params.role,
|
|
4577
|
+
chain: params.chain,
|
|
4578
|
+
normalizeExternalDestination: params.normalizeExternalDestination
|
|
4579
|
+
});
|
|
4580
|
+
}
|
|
4581
|
+
assertInstantLoanDestinationTypeMatchesChain({
|
|
4582
|
+
destinationType: params.destination.type,
|
|
4583
|
+
asset: params.asset,
|
|
4584
|
+
role: params.role,
|
|
4585
|
+
chain: params.chain
|
|
4586
|
+
});
|
|
4587
|
+
switch (params.destination.type) {
|
|
4588
|
+
case "ChainAddress":
|
|
4589
|
+
assertExternalInstantLoanDestinationSupported(params.asset);
|
|
4590
|
+
return {
|
|
4591
|
+
External: params.normalizeExternalDestination(
|
|
4592
|
+
normalizeInstantLoanDestinationAddress(params.destination.address),
|
|
4593
|
+
params.asset,
|
|
4594
|
+
params.chain
|
|
4595
|
+
)
|
|
4596
|
+
};
|
|
4597
|
+
case "IcPrincipal":
|
|
4598
|
+
return {
|
|
4599
|
+
Native: normalizeInstantLoanPrincipal(
|
|
4600
|
+
normalizeInstantLoanDestinationAddress(params.destination.address)
|
|
4601
|
+
)
|
|
4602
|
+
};
|
|
4603
|
+
case "IcpAccountIdentifier":
|
|
4604
|
+
return parseAccountIdentifierInstantLoanDestination(
|
|
4605
|
+
normalizeInstantLoanDestinationAddress(params.destination.address)
|
|
4606
|
+
);
|
|
4607
|
+
case "IcrcAccount":
|
|
4608
|
+
return parseIcrcInstantLoanDestination(
|
|
4609
|
+
normalizeInstantLoanDestinationAddress(params.destination.address)
|
|
4610
|
+
);
|
|
4611
|
+
}
|
|
4612
|
+
}
|
|
4613
|
+
function resolveInstantLoanStringDestination(params) {
|
|
4614
|
+
const address = normalizeInstantLoanDestinationAddress(params.destination);
|
|
4615
|
+
if (params.chain === Chain.ICP && params.asset !== Asset.ICP) {
|
|
4616
|
+
try {
|
|
4617
|
+
return parsePrincipalInstantLoanDestination(address);
|
|
4618
|
+
} catch {
|
|
4619
|
+
throwInvalidCkInstantLoanDestination(params.role);
|
|
4620
|
+
}
|
|
4621
|
+
}
|
|
4622
|
+
if (params.chain !== Chain.ICP) {
|
|
4623
|
+
assertExternalInstantLoanDestinationSupported(params.asset);
|
|
4624
|
+
return {
|
|
4625
|
+
External: params.normalizeExternalDestination(
|
|
4626
|
+
address,
|
|
4627
|
+
params.asset,
|
|
4628
|
+
params.chain
|
|
4629
|
+
)
|
|
4630
|
+
};
|
|
4631
|
+
}
|
|
4632
|
+
for (const parser of [
|
|
4633
|
+
parseAccountIdentifierInstantLoanDestination,
|
|
4634
|
+
parsePrincipalInstantLoanDestination,
|
|
4635
|
+
parseIcrcInstantLoanDestination
|
|
4636
|
+
]) {
|
|
4637
|
+
try {
|
|
4638
|
+
return parser(address);
|
|
4639
|
+
} catch {
|
|
4640
|
+
}
|
|
4641
|
+
}
|
|
4642
|
+
throwInvalidIcpInstantLoanDestination();
|
|
4643
|
+
}
|
|
4644
|
+
function getInstantLoanAssetIdentifier(asset, chain, role) {
|
|
4645
|
+
const identifier = { asset, chain };
|
|
4646
|
+
if (isAssetIdentifier(identifier)) {
|
|
4647
|
+
return identifier;
|
|
4648
|
+
}
|
|
4649
|
+
throw new LiquidiumError(
|
|
4650
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
4651
|
+
`${chain} instant loan ${role} delivery is not supported for ${asset}`
|
|
4652
|
+
);
|
|
4653
|
+
}
|
|
4654
|
+
function assertInstantLoanDestinationTypeMatchesChain(params) {
|
|
4655
|
+
if (params.chain === Chain.ICP && params.asset !== Asset.ICP) {
|
|
4656
|
+
if (params.destinationType === "IcPrincipal") {
|
|
4657
|
+
return;
|
|
4658
|
+
}
|
|
4659
|
+
throwInvalidCkInstantLoanDestination(params.role);
|
|
4660
|
+
}
|
|
4661
|
+
if (params.chain === Chain.ICP && params.asset === Asset.ICP) {
|
|
4662
|
+
if (params.destinationType !== "ChainAddress") {
|
|
4663
|
+
return;
|
|
4664
|
+
}
|
|
4665
|
+
throwInvalidIcpInstantLoanDestination();
|
|
4666
|
+
}
|
|
4667
|
+
if (params.destinationType === "ChainAddress") {
|
|
4668
|
+
return;
|
|
4669
|
+
}
|
|
4670
|
+
if (params.destinationType === "IcPrincipal") {
|
|
4324
4671
|
throw new LiquidiumError(
|
|
4325
4672
|
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
4326
|
-
|
|
4673
|
+
`${params.chain} instant loan ${params.role} destination must be an external chain address for ${params.asset}`
|
|
4327
4674
|
);
|
|
4328
4675
|
}
|
|
4329
|
-
|
|
4676
|
+
throw new LiquidiumError(
|
|
4677
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
4678
|
+
`${params.asset} instant loan ${params.role} destination only supports ChainAddress or IcPrincipal destinations`
|
|
4679
|
+
);
|
|
4330
4680
|
}
|
|
4331
|
-
function
|
|
4332
|
-
|
|
4333
|
-
|
|
4681
|
+
function throwInvalidCkInstantLoanDestination(role) {
|
|
4682
|
+
throw new LiquidiumError(
|
|
4683
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
4684
|
+
`ICP instant loan ${role} destination must be an IC principal`
|
|
4685
|
+
);
|
|
4686
|
+
}
|
|
4687
|
+
function assertExternalInstantLoanDestinationSupported(asset) {
|
|
4688
|
+
if (asset !== Asset.ICP) {
|
|
4689
|
+
return;
|
|
4334
4690
|
}
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4691
|
+
throwInvalidIcpInstantLoanDestination();
|
|
4692
|
+
}
|
|
4693
|
+
function throwInvalidIcpInstantLoanDestination() {
|
|
4694
|
+
throw new LiquidiumError(
|
|
4695
|
+
LiquidiumErrorCode.INVALID_ADDRESS,
|
|
4696
|
+
"ICP instant loan destination must be an IC principal, ICP account identifier, or ICRC account"
|
|
4697
|
+
);
|
|
4698
|
+
}
|
|
4699
|
+
function parsePrincipalInstantLoanDestination(address) {
|
|
4700
|
+
return { Native: normalizeInstantLoanPrincipal(address) };
|
|
4701
|
+
}
|
|
4702
|
+
function parseAccountIdentifierInstantLoanDestination(address) {
|
|
4703
|
+
if (address.length !== ICP_ACCOUNT_IDENTIFIER_HEX_LENGTH) {
|
|
4704
|
+
throw new LiquidiumError(
|
|
4705
|
+
LiquidiumErrorCode.INVALID_ADDRESS,
|
|
4706
|
+
"Invalid ICP account identifier"
|
|
4707
|
+
);
|
|
4340
4708
|
}
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
owner: account.Icrc.owner,
|
|
4349
|
-
subaccount
|
|
4350
|
-
})
|
|
4351
|
-
};
|
|
4709
|
+
try {
|
|
4710
|
+
return { AccountIdentifier: normalizeIcpAccountIdentifier(address) };
|
|
4711
|
+
} catch {
|
|
4712
|
+
throw new LiquidiumError(
|
|
4713
|
+
LiquidiumErrorCode.INVALID_ADDRESS,
|
|
4714
|
+
"Invalid ICP account identifier"
|
|
4715
|
+
);
|
|
4352
4716
|
}
|
|
4353
|
-
return { type: "External", address: account.External };
|
|
4354
4717
|
}
|
|
4355
|
-
function
|
|
4356
|
-
|
|
4357
|
-
|
|
4718
|
+
function parseIcrcInstantLoanDestination(address) {
|
|
4719
|
+
let decoded;
|
|
4720
|
+
try {
|
|
4721
|
+
decoded = decodeIcrcAccountAddress(address);
|
|
4722
|
+
} catch {
|
|
4723
|
+
throw new LiquidiumError(
|
|
4724
|
+
LiquidiumErrorCode.INVALID_ADDRESS,
|
|
4725
|
+
"Invalid instant loan ICRC destination"
|
|
4726
|
+
);
|
|
4727
|
+
}
|
|
4728
|
+
return { Icrc: decoded.account.address };
|
|
4729
|
+
}
|
|
4730
|
+
function normalizeInstantLoanPrincipal(address) {
|
|
4731
|
+
try {
|
|
4732
|
+
return principal.Principal.fromText(address).toText();
|
|
4733
|
+
} catch {
|
|
4734
|
+
throw new LiquidiumError(
|
|
4735
|
+
LiquidiumErrorCode.INVALID_ADDRESS,
|
|
4736
|
+
"Invalid instant loan IC principal destination"
|
|
4737
|
+
);
|
|
4358
4738
|
}
|
|
4359
|
-
|
|
4739
|
+
}
|
|
4740
|
+
function normalizeInstantLoanDestinationAddress(address) {
|
|
4741
|
+
const trimmedAddress = address.trim();
|
|
4742
|
+
if (!trimmedAddress) {
|
|
4743
|
+
throw new LiquidiumError(
|
|
4744
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
4745
|
+
"Instant loan account address must be non-empty"
|
|
4746
|
+
);
|
|
4747
|
+
}
|
|
4748
|
+
return trimmedAddress;
|
|
4749
|
+
}
|
|
4750
|
+
function accountFromCanister(account) {
|
|
4751
|
+
return mapCanisterAccountToLiquidiumAccount(account);
|
|
4360
4752
|
}
|
|
4361
4753
|
function mapInstantLoanEvent(event) {
|
|
4362
4754
|
return {
|
|
@@ -4373,7 +4765,10 @@ function mapInstantLoanEventType(eventType) {
|
|
|
4373
4765
|
type: "LoanCreated",
|
|
4374
4766
|
loanId: event.loan_id,
|
|
4375
4767
|
borrowDestination: accountFromCanister(event.borrow_destination),
|
|
4376
|
-
collateralAsset:
|
|
4768
|
+
collateralAsset: parseInstantLoanAsset(
|
|
4769
|
+
event.lend_asset,
|
|
4770
|
+
"event collateral asset"
|
|
4771
|
+
),
|
|
4377
4772
|
borrowAmount: event.borrow_amount,
|
|
4378
4773
|
collateralPoolId: event.lend_pool_id.toText(),
|
|
4379
4774
|
refundDestination: accountFromCanister(event.refund_destination),
|
|
@@ -4381,7 +4776,10 @@ function mapInstantLoanEventType(eventType) {
|
|
|
4381
4776
|
depositWindowSeconds: event.ltv_timer_s,
|
|
4382
4777
|
profileId: event.lending_profile.toText(),
|
|
4383
4778
|
borrowPoolId: event.borrow_pool_id.toText(),
|
|
4384
|
-
borrowAsset:
|
|
4779
|
+
borrowAsset: parseInstantLoanAsset(
|
|
4780
|
+
event.borrow_asset,
|
|
4781
|
+
"event borrow asset"
|
|
4782
|
+
)
|
|
4385
4783
|
};
|
|
4386
4784
|
}
|
|
4387
4785
|
if ("FullLendWithdrawalRequested" in eventType) {
|
|
@@ -4548,6 +4946,12 @@ function mapCandidateWire(wire) {
|
|
|
4548
4946
|
})
|
|
4549
4947
|
};
|
|
4550
4948
|
}
|
|
4949
|
+
function parseInstantLoanAsset(value, label) {
|
|
4950
|
+
return parseApiStringUnion(value, INSTANT_LOAN_ASSETS, {
|
|
4951
|
+
context: INSTANT_LOAN_WIRE_CONTEXT,
|
|
4952
|
+
label
|
|
4953
|
+
});
|
|
4954
|
+
}
|
|
4551
4955
|
function mapInstantLoansErrorToLiquidiumError(error) {
|
|
4552
4956
|
const [key, payload] = Object.entries(error)[0];
|
|
4553
4957
|
switch (key) {
|
|
@@ -4689,11 +5093,25 @@ function encodeBytes32Hex(bytes) {
|
|
|
4689
5093
|
var idlFactory4 = ({ IDL }) => IDL.Service({
|
|
4690
5094
|
icrc1_fee: IDL.Func([], [IDL.Nat], ["query"])
|
|
4691
5095
|
});
|
|
4692
|
-
function
|
|
4693
|
-
|
|
5096
|
+
function createIcrcLedgerActor(params) {
|
|
5097
|
+
if (!params.canisterId) {
|
|
5098
|
+
throw new LiquidiumError(
|
|
5099
|
+
LiquidiumErrorCode.SERVICE_UNAVAILABLE,
|
|
5100
|
+
`${params.ledgerName} ledger canister ID is not configured`
|
|
5101
|
+
);
|
|
5102
|
+
}
|
|
4694
5103
|
return agent.Actor.createActor(idlFactory4, {
|
|
4695
|
-
agent: canisterContext.agent,
|
|
4696
|
-
canisterId
|
|
5104
|
+
agent: params.canisterContext.agent,
|
|
5105
|
+
canisterId: params.canisterId
|
|
5106
|
+
});
|
|
5107
|
+
}
|
|
5108
|
+
|
|
5109
|
+
// src/core/canisters/ckbtc/ledger.ts
|
|
5110
|
+
function createCkBtcLedgerActor(canisterContext) {
|
|
5111
|
+
return createIcrcLedgerActor({
|
|
5112
|
+
canisterContext,
|
|
5113
|
+
canisterId: CK_CANISTER_IDS.BTC.ledger,
|
|
5114
|
+
ledgerName: "ckBTC"
|
|
4697
5115
|
});
|
|
4698
5116
|
}
|
|
4699
5117
|
|
|
@@ -4722,11 +5140,51 @@ function accountTypeToString(accountType) {
|
|
|
4722
5140
|
switch (accountType.type) {
|
|
4723
5141
|
case "External":
|
|
4724
5142
|
return `Address:${accountType.data}`;
|
|
5143
|
+
case "Icrc":
|
|
5144
|
+
return `Icrc:${accountType.data}`;
|
|
5145
|
+
case "AccountIdentifier":
|
|
5146
|
+
return `AccountId:${accountType.data}`;
|
|
4725
5147
|
case "Native":
|
|
4726
5148
|
return `Principal:${accountType.data}`;
|
|
4727
5149
|
}
|
|
4728
5150
|
}
|
|
4729
5151
|
|
|
5152
|
+
// src/core/pool-ledger-assets.ts
|
|
5153
|
+
function getPoolLedgerAssetRoute(params) {
|
|
5154
|
+
if (params.asset === Asset.BTC && (params.chain === Chain.BTC || params.chain === Chain.ICP)) {
|
|
5155
|
+
return {
|
|
5156
|
+
ledgerCanisterId: CK_CANISTER_IDS.BTC.ledger,
|
|
5157
|
+
asset: Asset.BTC,
|
|
5158
|
+
chain: params.chain
|
|
5159
|
+
};
|
|
5160
|
+
}
|
|
5161
|
+
if (params.asset === Asset.USDT && (params.chain === Chain.ETH || params.chain === Chain.ICP)) {
|
|
5162
|
+
return {
|
|
5163
|
+
ledgerCanisterId: CK_CANISTER_IDS.USDT.ledger,
|
|
5164
|
+
asset: Asset.USDT,
|
|
5165
|
+
chain: params.chain
|
|
5166
|
+
};
|
|
5167
|
+
}
|
|
5168
|
+
if (params.asset === Asset.USDC && (params.chain === Chain.ETH || params.chain === Chain.ICP)) {
|
|
5169
|
+
return {
|
|
5170
|
+
ledgerCanisterId: CK_CANISTER_IDS.USDC.ledger,
|
|
5171
|
+
asset: Asset.USDC,
|
|
5172
|
+
chain: params.chain
|
|
5173
|
+
};
|
|
5174
|
+
}
|
|
5175
|
+
if (params.asset === Asset.ICP && params.chain === Chain.ICP) {
|
|
5176
|
+
return {
|
|
5177
|
+
ledgerCanisterId: CK_CANISTER_IDS.ICP.ledger,
|
|
5178
|
+
asset: Asset.ICP,
|
|
5179
|
+
chain: Chain.ICP
|
|
5180
|
+
};
|
|
5181
|
+
}
|
|
5182
|
+
throw new LiquidiumError(
|
|
5183
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
5184
|
+
`IC ledger transfers are not supported for ${params.asset} on ${params.chain}`
|
|
5185
|
+
);
|
|
5186
|
+
}
|
|
5187
|
+
|
|
4730
5188
|
// src/core/withdraw-minimums.ts
|
|
4731
5189
|
var MINIMUM_BTC_WITHDRAW_AMOUNT_SATS = 5000n;
|
|
4732
5190
|
var MINIMUM_STABLECOIN_WITHDRAW_AMOUNT_BASE_UNITS = 1000000n;
|
|
@@ -4844,48 +5302,61 @@ var SupplyFlowExecutor = class {
|
|
|
4844
5302
|
}
|
|
4845
5303
|
params;
|
|
4846
5304
|
async create(request) {
|
|
4847
|
-
const
|
|
5305
|
+
const requestedMechanism = request.mechanism ?? null;
|
|
5306
|
+
if (requestedMechanism === null && request.walletAdapter === void 0 && (request.account !== void 0 || request.amount !== void 0)) {
|
|
5307
|
+
throw new LiquidiumError(
|
|
5308
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
5309
|
+
"Wallet-executed supply requires walletAdapter, account, and amount"
|
|
5310
|
+
);
|
|
5311
|
+
}
|
|
5312
|
+
const selectedPool = await getPoolById(
|
|
4848
5313
|
this.params.canisterContext,
|
|
4849
|
-
request
|
|
5314
|
+
request.poolId
|
|
4850
5315
|
);
|
|
4851
|
-
const
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
5316
|
+
const target = await resolveSupplyTargetForPool(
|
|
5317
|
+
this.params.canisterContext,
|
|
5318
|
+
{
|
|
5319
|
+
profileId: request.profileId,
|
|
5320
|
+
poolId: request.poolId,
|
|
5321
|
+
action: request.action,
|
|
5322
|
+
mechanism: requestedMechanism,
|
|
5323
|
+
chain: request.chain
|
|
5324
|
+
},
|
|
5325
|
+
selectedPool
|
|
5326
|
+
);
|
|
5327
|
+
const mechanism = requestedMechanism === SupplyPlanType.contractInteraction ? SupplyPlanType.contractInteraction : SupplyPlanType.transfer;
|
|
4863
5328
|
const defaultSubmitInflowRequest = getDefaultSubmitInflowRequest({
|
|
4864
5329
|
action: request.action,
|
|
4865
|
-
chain: mechanism === SupplyPlanType.contractInteraction ? Chain.ETH :
|
|
5330
|
+
chain: mechanism === SupplyPlanType.contractInteraction ? Chain.ETH : target.chain
|
|
4866
5331
|
});
|
|
4867
5332
|
let txid;
|
|
4868
5333
|
switch (mechanism) {
|
|
4869
5334
|
case SupplyPlanType.transfer:
|
|
4870
|
-
if (request
|
|
4871
|
-
txid = await this.
|
|
5335
|
+
if (isWalletTransferSupplyRequest(request)) {
|
|
5336
|
+
txid = await this.sendAndSubmitTransferSupplyInflow({
|
|
4872
5337
|
request,
|
|
4873
|
-
|
|
5338
|
+
target,
|
|
4874
5339
|
defaultSubmitInflowRequest
|
|
4875
5340
|
});
|
|
4876
5341
|
}
|
|
4877
5342
|
break;
|
|
4878
5343
|
case SupplyPlanType.contractInteraction:
|
|
5344
|
+
if (!isContractInteractionSupplyRequest(request)) {
|
|
5345
|
+
throw new LiquidiumError(
|
|
5346
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
5347
|
+
"Contract-interaction supply requires contract-interaction request fields"
|
|
5348
|
+
);
|
|
5349
|
+
}
|
|
4879
5350
|
txid = await this.executeContractSupply({
|
|
4880
5351
|
request,
|
|
4881
|
-
|
|
5352
|
+
target,
|
|
4882
5353
|
defaultSubmitInflowRequest
|
|
4883
5354
|
});
|
|
4884
5355
|
break;
|
|
4885
5356
|
}
|
|
4886
5357
|
return {
|
|
4887
5358
|
type: mechanism,
|
|
4888
|
-
target
|
|
5359
|
+
target,
|
|
4889
5360
|
txid,
|
|
4890
5361
|
status: createLiquidiumStatus({
|
|
4891
5362
|
operation: mapSupplyActionToStatusOperation(request.action),
|
|
@@ -4893,7 +5364,7 @@ var SupplyFlowExecutor = class {
|
|
|
4893
5364
|
}),
|
|
4894
5365
|
submit: async (submitRequest) => {
|
|
4895
5366
|
return await this.submitSupplyFlowInflow({
|
|
4896
|
-
|
|
5367
|
+
target,
|
|
4897
5368
|
mechanism,
|
|
4898
5369
|
defaultSubmitInflowRequest,
|
|
4899
5370
|
submitRequest
|
|
@@ -4902,7 +5373,10 @@ var SupplyFlowExecutor = class {
|
|
|
4902
5373
|
};
|
|
4903
5374
|
}
|
|
4904
5375
|
async getEvmSupplyContext(request) {
|
|
4905
|
-
const selectedPool = await
|
|
5376
|
+
const selectedPool = await getPoolById(
|
|
5377
|
+
this.params.canisterContext,
|
|
5378
|
+
request.poolId
|
|
5379
|
+
);
|
|
4906
5380
|
return await this.getEvmSupplyContextForPool({
|
|
4907
5381
|
request,
|
|
4908
5382
|
asset: selectedPool.asset,
|
|
@@ -4966,14 +5440,8 @@ var SupplyFlowExecutor = class {
|
|
|
4966
5440
|
approvalStrategy
|
|
4967
5441
|
};
|
|
4968
5442
|
}
|
|
4969
|
-
async
|
|
4970
|
-
const { request,
|
|
4971
|
-
if (instruction.target.type !== "nativeAddress") {
|
|
4972
|
-
throw new LiquidiumError(
|
|
4973
|
-
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
4974
|
-
"Wallet-executed supply requires a native-address target"
|
|
4975
|
-
);
|
|
4976
|
-
}
|
|
5443
|
+
async sendAndSubmitTransferSupplyInflow(params) {
|
|
5444
|
+
const { request, target, defaultSubmitInflowRequest } = params;
|
|
4977
5445
|
if (!request.walletAdapter) {
|
|
4978
5446
|
throw new LiquidiumError(
|
|
4979
5447
|
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
@@ -4993,16 +5461,27 @@ var SupplyFlowExecutor = class {
|
|
|
4993
5461
|
"Wallet-executed supply requires a positive amount"
|
|
4994
5462
|
);
|
|
4995
5463
|
}
|
|
4996
|
-
const txid = await this.
|
|
5464
|
+
const txid = target.chain === Chain.ICP ? await this.sendIcrcSupplyTransaction({
|
|
4997
5465
|
walletAdapter: request.walletAdapter,
|
|
4998
|
-
|
|
4999
|
-
|
|
5466
|
+
asset: target.asset,
|
|
5467
|
+
chain: target.chain,
|
|
5468
|
+
transfer: {
|
|
5469
|
+
ledgerCanisterId: getPoolLedgerAssetRoute(target).ledgerCanisterId,
|
|
5470
|
+
to: decodeIcrcAccountAddress(target.address).account,
|
|
5471
|
+
amount: request.amount
|
|
5472
|
+
},
|
|
5473
|
+
senderAccount: account,
|
|
5474
|
+
action: request.action
|
|
5475
|
+
}) : await this.sendChainAddressSupplyTransaction({
|
|
5476
|
+
walletAdapter: request.walletAdapter,
|
|
5477
|
+
chain: target.chain,
|
|
5478
|
+
toAddress: target.address,
|
|
5000
5479
|
amount: request.amount,
|
|
5001
5480
|
senderAccount: account,
|
|
5002
|
-
asset:
|
|
5481
|
+
asset: target.asset,
|
|
5003
5482
|
action: request.action
|
|
5004
5483
|
});
|
|
5005
|
-
if (shouldSubmitInflow({
|
|
5484
|
+
if (shouldSubmitInflow({ target, mechanism: SupplyPlanType.transfer })) {
|
|
5006
5485
|
try {
|
|
5007
5486
|
await this.submitInflowWithRetry(txid, defaultSubmitInflowRequest);
|
|
5008
5487
|
} catch {
|
|
@@ -5029,11 +5508,11 @@ var SupplyFlowExecutor = class {
|
|
|
5029
5508
|
});
|
|
5030
5509
|
}
|
|
5031
5510
|
async executeContractSupply(params) {
|
|
5032
|
-
const { request,
|
|
5033
|
-
if (
|
|
5511
|
+
const { request, target, defaultSubmitInflowRequest } = params;
|
|
5512
|
+
if (!isEthStablecoin(target.asset, target.chain)) {
|
|
5034
5513
|
throw new LiquidiumError(
|
|
5035
5514
|
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
5036
|
-
"Contract-interaction supply is only supported for ETH
|
|
5515
|
+
"Contract-interaction supply is only supported for ETH stablecoin targets"
|
|
5037
5516
|
);
|
|
5038
5517
|
}
|
|
5039
5518
|
const walletAddressInput = request.account?.trim();
|
|
@@ -5072,8 +5551,8 @@ var SupplyFlowExecutor = class {
|
|
|
5072
5551
|
amount: request.amount,
|
|
5073
5552
|
action: request.action
|
|
5074
5553
|
},
|
|
5075
|
-
asset:
|
|
5076
|
-
chain:
|
|
5554
|
+
asset: target.asset,
|
|
5555
|
+
chain: target.chain
|
|
5077
5556
|
});
|
|
5078
5557
|
const supplyAmount = BigInt(evmSupplyContext.amount);
|
|
5079
5558
|
if (BigInt(evmSupplyContext.balance) < supplyAmount) {
|
|
@@ -5129,7 +5608,7 @@ var SupplyFlowExecutor = class {
|
|
|
5129
5608
|
amount: supplyAmount,
|
|
5130
5609
|
poolId: request.poolId,
|
|
5131
5610
|
profileId: request.profileId,
|
|
5132
|
-
destinationAccount:
|
|
5611
|
+
destinationAccount: target.address,
|
|
5133
5612
|
action: request.action
|
|
5134
5613
|
}),
|
|
5135
5614
|
`supply-${request.action}-deposit-erc20`
|
|
@@ -5140,7 +5619,7 @@ var SupplyFlowExecutor = class {
|
|
|
5140
5619
|
}
|
|
5141
5620
|
return depositTxid;
|
|
5142
5621
|
}
|
|
5143
|
-
async
|
|
5622
|
+
async sendChainAddressSupplyTransaction(params) {
|
|
5144
5623
|
switch (params.chain) {
|
|
5145
5624
|
case Chain.BTC: {
|
|
5146
5625
|
if (!params.walletAdapter.sendBtcTransaction) {
|
|
@@ -5154,8 +5633,7 @@ var SupplyFlowExecutor = class {
|
|
|
5154
5633
|
toAddress: params.toAddress,
|
|
5155
5634
|
amountSats: params.amount,
|
|
5156
5635
|
account: params.senderAccount,
|
|
5157
|
-
actionType: `supply-${params.action}
|
|
5158
|
-
transferMode: TransferMode.native
|
|
5636
|
+
actionType: `supply-${params.action}`
|
|
5159
5637
|
});
|
|
5160
5638
|
}
|
|
5161
5639
|
case Chain.ETH: {
|
|
@@ -5170,7 +5648,6 @@ var SupplyFlowExecutor = class {
|
|
|
5170
5648
|
chain: Chain.ETH,
|
|
5171
5649
|
account: params.senderAccount,
|
|
5172
5650
|
actionType: `supply-${params.action}`,
|
|
5173
|
-
transferMode: TransferMode.native,
|
|
5174
5651
|
transaction: createTransferErc20Transaction({
|
|
5175
5652
|
tokenAddress: getEthStablecoinContractAddress(params.asset),
|
|
5176
5653
|
recipientAddress: params.toAddress,
|
|
@@ -5182,7 +5659,6 @@ var SupplyFlowExecutor = class {
|
|
|
5182
5659
|
chain: Chain.ETH,
|
|
5183
5660
|
account: params.senderAccount,
|
|
5184
5661
|
actionType: `supply-${params.action}`,
|
|
5185
|
-
transferMode: TransferMode.native,
|
|
5186
5662
|
transaction: {
|
|
5187
5663
|
to: params.toAddress,
|
|
5188
5664
|
value: params.amount.toString()
|
|
@@ -5192,10 +5668,32 @@ var SupplyFlowExecutor = class {
|
|
|
5192
5668
|
default:
|
|
5193
5669
|
throw new LiquidiumError(
|
|
5194
5670
|
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
5195
|
-
`
|
|
5671
|
+
`Chain-address wallet execution is not supported for ${params.chain}`
|
|
5196
5672
|
);
|
|
5197
5673
|
}
|
|
5198
5674
|
}
|
|
5675
|
+
async sendIcrcSupplyTransaction(params) {
|
|
5676
|
+
if (!params.walletAdapter.sendIcrcTransfer) {
|
|
5677
|
+
throw new LiquidiumError(
|
|
5678
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
5679
|
+
"ICRC wallet adapter does not support ledger transfers"
|
|
5680
|
+
);
|
|
5681
|
+
}
|
|
5682
|
+
const route = getPoolLedgerAssetRoute({
|
|
5683
|
+
asset: params.asset,
|
|
5684
|
+
chain: params.chain
|
|
5685
|
+
});
|
|
5686
|
+
return await params.walletAdapter.sendIcrcTransfer({
|
|
5687
|
+
chain: Chain.ICP,
|
|
5688
|
+
asset: route.asset,
|
|
5689
|
+
transfer: {
|
|
5690
|
+
...params.transfer,
|
|
5691
|
+
ledgerCanisterId: route.ledgerCanisterId
|
|
5692
|
+
},
|
|
5693
|
+
account: params.senderAccount,
|
|
5694
|
+
actionType: `supply-${params.action}`
|
|
5695
|
+
});
|
|
5696
|
+
}
|
|
5199
5697
|
async submitInflowWithRetry(txid, extraRequest) {
|
|
5200
5698
|
if (!extraRequest) {
|
|
5201
5699
|
throw new LiquidiumError(
|
|
@@ -5224,7 +5722,6 @@ var SupplyFlowExecutor = class {
|
|
|
5224
5722
|
chain: Chain.ETH,
|
|
5225
5723
|
account: walletAddress,
|
|
5226
5724
|
actionType,
|
|
5227
|
-
transferMode: TransferMode.native,
|
|
5228
5725
|
transaction: request
|
|
5229
5726
|
});
|
|
5230
5727
|
}
|
|
@@ -5313,13 +5810,19 @@ function getUnknownErrorMessage(error) {
|
|
|
5313
5810
|
}
|
|
5314
5811
|
function getDefaultSubmitInflowRequest(params) {
|
|
5315
5812
|
if (params.chain !== Chain.BTC && params.chain !== Chain.ETH) {
|
|
5316
|
-
return
|
|
5813
|
+
return null;
|
|
5317
5814
|
}
|
|
5318
5815
|
return {
|
|
5319
5816
|
chain: params.chain,
|
|
5320
5817
|
operation: mapSupplyActionToStatusOperation(params.action)
|
|
5321
5818
|
};
|
|
5322
5819
|
}
|
|
5820
|
+
function isWalletTransferSupplyRequest(request) {
|
|
5821
|
+
return request.mechanism !== SupplyPlanType.contractInteraction && request.walletAdapter !== void 0;
|
|
5822
|
+
}
|
|
5823
|
+
function isContractInteractionSupplyRequest(request) {
|
|
5824
|
+
return request.mechanism === SupplyPlanType.contractInteraction;
|
|
5825
|
+
}
|
|
5323
5826
|
function mapSupplyActionToStatusOperation(action) {
|
|
5324
5827
|
return action === SupplyAction.repayment ? "repayment" : "deposit";
|
|
5325
5828
|
}
|
|
@@ -5327,7 +5830,10 @@ function shouldSubmitInflow(params) {
|
|
|
5327
5830
|
if (params.mechanism !== SupplyPlanType.transfer) {
|
|
5328
5831
|
return true;
|
|
5329
5832
|
}
|
|
5330
|
-
|
|
5833
|
+
if (params.target.chain === Chain.ICP) {
|
|
5834
|
+
return false;
|
|
5835
|
+
}
|
|
5836
|
+
return !isEthStablecoin(params.target.asset, params.target.chain);
|
|
5331
5837
|
}
|
|
5332
5838
|
function mapCanisterOutflowDetails(outflow) {
|
|
5333
5839
|
const rawOutflowType = getVariantKey(outflow.outflow_type);
|
|
@@ -5341,41 +5847,31 @@ function mapCanisterOutflowDetails(outflow) {
|
|
|
5341
5847
|
};
|
|
5342
5848
|
}
|
|
5343
5849
|
function mapCanisterAccountType(receiver) {
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
if ("Icrc" in receiver) {
|
|
5357
|
-
const subaccount = normalizeOptionalSubaccount2(receiver.Icrc.subaccount[0]);
|
|
5358
|
-
return {
|
|
5359
|
-
type: "Icrc",
|
|
5360
|
-
owner: receiver.Icrc.owner.toText(),
|
|
5361
|
-
subaccount,
|
|
5362
|
-
account: icrc.encodeIcrcAccount({
|
|
5363
|
-
owner: receiver.Icrc.owner,
|
|
5364
|
-
subaccount
|
|
5365
|
-
})
|
|
5366
|
-
};
|
|
5850
|
+
return mapCanisterAccountToLiquidiumAccount(receiver);
|
|
5851
|
+
}
|
|
5852
|
+
function parseOutflowDestination(params) {
|
|
5853
|
+
const destination = normalizeOutflowDestinationInput(params.destination);
|
|
5854
|
+
const parsedAccount = destination.type ? parseOutflowDestinationWithHint(destination) : parseOutflowDestinationAutomatically(destination.address);
|
|
5855
|
+
assertDestinationTypeSupportedByChain({
|
|
5856
|
+
accountType: parsedAccount.accountType,
|
|
5857
|
+
poolChain: params.poolChain,
|
|
5858
|
+
destinationChain: params.destinationChain
|
|
5859
|
+
});
|
|
5860
|
+
if (parsedAccount.accountType !== "ChainAddress") {
|
|
5861
|
+
return parsedAccount;
|
|
5367
5862
|
}
|
|
5863
|
+
const externalAddress = normalizeExternalAddress({
|
|
5864
|
+
address: parsedAccount.address,
|
|
5865
|
+
asset: params.asset,
|
|
5866
|
+
chain: params.destinationChain
|
|
5867
|
+
});
|
|
5368
5868
|
return {
|
|
5369
|
-
|
|
5370
|
-
|
|
5869
|
+
address: externalAddress,
|
|
5870
|
+
accountType: "ChainAddress",
|
|
5871
|
+
canisterAccount: { External: externalAddress },
|
|
5872
|
+
messageAccount: { type: "External", data: externalAddress }
|
|
5371
5873
|
};
|
|
5372
5874
|
}
|
|
5373
|
-
function normalizeOptionalSubaccount2(subaccount) {
|
|
5374
|
-
if (!subaccount) {
|
|
5375
|
-
return void 0;
|
|
5376
|
-
}
|
|
5377
|
-
return subaccount instanceof Uint8Array ? subaccount : Uint8Array.from(subaccount);
|
|
5378
|
-
}
|
|
5379
5875
|
function normalizeOutflowType(rawOutflowType) {
|
|
5380
5876
|
switch (rawOutflowType) {
|
|
5381
5877
|
case "Withdraw":
|
|
@@ -5398,6 +5894,117 @@ function mapWalletChainToLendingChain(chain) {
|
|
|
5398
5894
|
case Chain.ETH:
|
|
5399
5895
|
return { ETH: null };
|
|
5400
5896
|
}
|
|
5897
|
+
throw new LiquidiumError(
|
|
5898
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
5899
|
+
`Message signing is not supported for ${String(chain)}`
|
|
5900
|
+
);
|
|
5901
|
+
}
|
|
5902
|
+
function normalizeOutflowDestinationInput(destination) {
|
|
5903
|
+
if (typeof destination === "string") {
|
|
5904
|
+
return { address: destination, type: null };
|
|
5905
|
+
}
|
|
5906
|
+
return destination;
|
|
5907
|
+
}
|
|
5908
|
+
function parseOutflowDestinationWithHint(destination) {
|
|
5909
|
+
try {
|
|
5910
|
+
switch (destination.type) {
|
|
5911
|
+
case "ChainAddress":
|
|
5912
|
+
return parseExternalDestination(destination.address);
|
|
5913
|
+
case "IcPrincipal":
|
|
5914
|
+
return parseIcPrincipalDestination(destination.address);
|
|
5915
|
+
case "IcrcAccount":
|
|
5916
|
+
return parseIcrcDestination(destination.address);
|
|
5917
|
+
case "IcpAccountIdentifier":
|
|
5918
|
+
return parseAccountIdentifierDestination(destination.address);
|
|
5919
|
+
default:
|
|
5920
|
+
throw new LiquidiumError(
|
|
5921
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
5922
|
+
`Unsupported outflow account type: ${String(destination.type)}`
|
|
5923
|
+
);
|
|
5924
|
+
}
|
|
5925
|
+
} catch (error) {
|
|
5926
|
+
if (error instanceof LiquidiumError) {
|
|
5927
|
+
throw error;
|
|
5928
|
+
}
|
|
5929
|
+
throw new LiquidiumError(
|
|
5930
|
+
LiquidiumErrorCode.INVALID_ADDRESS,
|
|
5931
|
+
`Invalid ${destination.type} outflow destination`
|
|
5932
|
+
);
|
|
5933
|
+
}
|
|
5934
|
+
}
|
|
5935
|
+
function parseOutflowDestinationAutomatically(address) {
|
|
5936
|
+
const parsers = [
|
|
5937
|
+
parseAccountIdentifierDestination,
|
|
5938
|
+
parseIcPrincipalDestination,
|
|
5939
|
+
parseIcrcDestination
|
|
5940
|
+
];
|
|
5941
|
+
for (const parser of parsers) {
|
|
5942
|
+
try {
|
|
5943
|
+
return parser(address);
|
|
5944
|
+
} catch {
|
|
5945
|
+
}
|
|
5946
|
+
}
|
|
5947
|
+
return parseExternalDestination(address);
|
|
5948
|
+
}
|
|
5949
|
+
function parseExternalDestination(address) {
|
|
5950
|
+
return {
|
|
5951
|
+
address,
|
|
5952
|
+
accountType: "ChainAddress",
|
|
5953
|
+
canisterAccount: { External: address },
|
|
5954
|
+
messageAccount: { type: "External", data: address }
|
|
5955
|
+
};
|
|
5956
|
+
}
|
|
5957
|
+
function parseIcPrincipalDestination(address) {
|
|
5958
|
+
const principal$1 = principal.Principal.fromText(address);
|
|
5959
|
+
const principalText = principal$1.toText();
|
|
5960
|
+
return {
|
|
5961
|
+
address: principalText,
|
|
5962
|
+
accountType: "IcPrincipal",
|
|
5963
|
+
canisterAccount: { Native: principal$1 },
|
|
5964
|
+
messageAccount: { type: "Native", data: principalText }
|
|
5965
|
+
};
|
|
5966
|
+
}
|
|
5967
|
+
function parseIcrcDestination(address) {
|
|
5968
|
+
const decoded = decodeIcrcAccountAddress(address);
|
|
5969
|
+
return {
|
|
5970
|
+
address: decoded.account.address,
|
|
5971
|
+
accountType: "IcrcAccount",
|
|
5972
|
+
canisterAccount: {
|
|
5973
|
+
Icrc: {
|
|
5974
|
+
owner: decoded.owner,
|
|
5975
|
+
subaccount: decoded.subaccount ? [decoded.subaccount] : []
|
|
5976
|
+
}
|
|
5977
|
+
},
|
|
5978
|
+
messageAccount: { type: "Icrc", data: decoded.account.address }
|
|
5979
|
+
};
|
|
5980
|
+
}
|
|
5981
|
+
function parseAccountIdentifierDestination(address) {
|
|
5982
|
+
const accountIdentifier = normalizeIcpAccountIdentifier(address);
|
|
5983
|
+
return {
|
|
5984
|
+
address: accountIdentifier,
|
|
5985
|
+
accountType: "IcpAccountIdentifier",
|
|
5986
|
+
canisterAccount: { AccountIdentifier: accountIdentifier },
|
|
5987
|
+
messageAccount: { type: "AccountIdentifier", data: accountIdentifier }
|
|
5988
|
+
};
|
|
5989
|
+
}
|
|
5990
|
+
function assertDestinationTypeSupportedByChain(params) {
|
|
5991
|
+
if (params.poolChain === Chain.BTC || params.poolChain === Chain.ETH) {
|
|
5992
|
+
if (params.destinationChain === params.poolChain && params.accountType === "ChainAddress") {
|
|
5993
|
+
return;
|
|
5994
|
+
}
|
|
5995
|
+
if (params.destinationChain === Chain.ICP && params.accountType === "IcPrincipal") {
|
|
5996
|
+
return;
|
|
5997
|
+
}
|
|
5998
|
+
}
|
|
5999
|
+
if (params.poolChain === Chain.ICP && params.destinationChain === Chain.ICP) {
|
|
6000
|
+
if (params.accountType === "IcpAccountIdentifier" || params.accountType === "IcrcAccount" || params.accountType === "IcPrincipal") {
|
|
6001
|
+
return;
|
|
6002
|
+
}
|
|
6003
|
+
}
|
|
6004
|
+
throw new LiquidiumError(
|
|
6005
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
6006
|
+
"Target pool does not support this address type"
|
|
6007
|
+
);
|
|
5401
6008
|
}
|
|
5402
6009
|
|
|
5403
6010
|
// src/modules/lending/lending.ts
|
|
@@ -5419,16 +6026,13 @@ var LendingModule = class {
|
|
|
5419
6026
|
* @returns A signable {@link WithdrawAction} with `submit` wired to the canister.
|
|
5420
6027
|
*/
|
|
5421
6028
|
async prepareWithdraw(request) {
|
|
5422
|
-
const
|
|
6029
|
+
const destination = resolveOutflowDestinationInput({
|
|
6030
|
+
receiver: request.receiver,
|
|
6031
|
+
errorMessage: "Withdraw requires a custom outflow account"
|
|
6032
|
+
});
|
|
5423
6033
|
const signerAccount = normalizeEvmAddress(
|
|
5424
6034
|
request.signerWalletAddress.trim()
|
|
5425
6035
|
);
|
|
5426
|
-
if (!destinationAccount) {
|
|
5427
|
-
throw new LiquidiumError(
|
|
5428
|
-
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
5429
|
-
"Withdraw requires a custom outflow account"
|
|
5430
|
-
);
|
|
5431
|
-
}
|
|
5432
6036
|
if (!signerAccount) {
|
|
5433
6037
|
throw new LiquidiumError(
|
|
5434
6038
|
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
@@ -5441,7 +6045,10 @@ var LendingModule = class {
|
|
|
5441
6045
|
"Withdraw amount must be greater than 0"
|
|
5442
6046
|
);
|
|
5443
6047
|
}
|
|
5444
|
-
const selectedPool = await
|
|
6048
|
+
const selectedPool = await getPoolById(
|
|
6049
|
+
this.canisterContext,
|
|
6050
|
+
request.poolId
|
|
6051
|
+
);
|
|
5445
6052
|
const selectedAsset = selectedPool.asset;
|
|
5446
6053
|
const minimumWithdrawAmountError = getWithdrawAmountMinimumValidationError({
|
|
5447
6054
|
amount: request.amount,
|
|
@@ -5453,41 +6060,52 @@ var LendingModule = class {
|
|
|
5453
6060
|
minimumWithdrawAmountError.message
|
|
5454
6061
|
);
|
|
5455
6062
|
}
|
|
5456
|
-
const
|
|
5457
|
-
|
|
6063
|
+
const receiver = parseOutflowDestination({
|
|
6064
|
+
destination,
|
|
5458
6065
|
asset: selectedAsset,
|
|
5459
|
-
|
|
6066
|
+
poolChain: selectedPool.chain,
|
|
6067
|
+
destinationChain: request.chain
|
|
5460
6068
|
});
|
|
5461
6069
|
const lendingActor = createLendingActor(this.canisterContext);
|
|
5462
6070
|
try {
|
|
5463
6071
|
const expiryTimestamp = computeExpiryTimestampFromNow();
|
|
5464
6072
|
const nonce = await lendingActor.get_nonce(signerAccount);
|
|
5465
|
-
const
|
|
6073
|
+
const withdrawActionData = {
|
|
5466
6074
|
profileId: request.profileId,
|
|
5467
6075
|
poolId: request.poolId,
|
|
5468
6076
|
amount: request.amount,
|
|
5469
|
-
|
|
6077
|
+
chain: request.chain,
|
|
6078
|
+
receiver: {
|
|
6079
|
+
address: receiver.address,
|
|
6080
|
+
type: receiver.accountType
|
|
6081
|
+
},
|
|
5470
6082
|
signerWalletAddress: signerAccount,
|
|
5471
6083
|
expiryTimestamp
|
|
5472
6084
|
};
|
|
6085
|
+
const withdrawSubmissionData = {
|
|
6086
|
+
...withdrawActionData,
|
|
6087
|
+
receiverAccount: receiver.canisterAccount
|
|
6088
|
+
};
|
|
5473
6089
|
return {
|
|
5474
6090
|
kind: WalletActionKind.createWithdraw,
|
|
5475
6091
|
executionKind: WalletExecutionKind.signMessage,
|
|
5476
6092
|
actionType: WalletActionKind.createWithdraw,
|
|
5477
|
-
transferMode: TransferMode.native,
|
|
5478
6093
|
account: signerAccount,
|
|
5479
6094
|
message: createWithdrawAssetMessage(
|
|
5480
6095
|
{
|
|
5481
6096
|
pool_id: request.poolId,
|
|
5482
6097
|
amount: request.amount.toString(),
|
|
5483
|
-
account:
|
|
6098
|
+
account: receiver.messageAccount,
|
|
5484
6099
|
expiry_timestamp: expiryTimestamp
|
|
5485
6100
|
},
|
|
5486
6101
|
nonce
|
|
5487
6102
|
),
|
|
5488
|
-
data:
|
|
6103
|
+
data: withdrawActionData,
|
|
5489
6104
|
submit: async (signatureInfo) => {
|
|
5490
|
-
return await this.submitWithdraw(
|
|
6105
|
+
return await this.submitWithdraw(
|
|
6106
|
+
withdrawSubmissionData,
|
|
6107
|
+
signatureInfo
|
|
6108
|
+
);
|
|
5491
6109
|
}
|
|
5492
6110
|
};
|
|
5493
6111
|
} catch (error) {
|
|
@@ -5504,7 +6122,7 @@ var LendingModule = class {
|
|
|
5504
6122
|
{
|
|
5505
6123
|
data: {
|
|
5506
6124
|
expiry_timestamp: request.expiryTimestamp,
|
|
5507
|
-
account:
|
|
6125
|
+
account: request.receiverAccount,
|
|
5508
6126
|
pool_id: principal.Principal.fromText(request.poolId),
|
|
5509
6127
|
amount: request.amount
|
|
5510
6128
|
},
|
|
@@ -5560,16 +6178,13 @@ var LendingModule = class {
|
|
|
5560
6178
|
* @returns A signable {@link BorrowAction} with `submit` wired to the canister.
|
|
5561
6179
|
*/
|
|
5562
6180
|
async prepareBorrow(request) {
|
|
5563
|
-
const
|
|
6181
|
+
const destination = resolveOutflowDestinationInput({
|
|
6182
|
+
receiver: request.receiver,
|
|
6183
|
+
errorMessage: "Borrow requires a custom outflow account"
|
|
6184
|
+
});
|
|
5564
6185
|
const signerAccount = normalizeEvmAddress(
|
|
5565
6186
|
request.signerWalletAddress.trim()
|
|
5566
6187
|
);
|
|
5567
|
-
if (!destinationAccount) {
|
|
5568
|
-
throw new LiquidiumError(
|
|
5569
|
-
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
5570
|
-
"Borrow requires a custom outflow account"
|
|
5571
|
-
);
|
|
5572
|
-
}
|
|
5573
6188
|
if (!signerAccount) {
|
|
5574
6189
|
throw new LiquidiumError(
|
|
5575
6190
|
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
@@ -5582,7 +6197,10 @@ var LendingModule = class {
|
|
|
5582
6197
|
"Borrow amount must be greater than 0"
|
|
5583
6198
|
);
|
|
5584
6199
|
}
|
|
5585
|
-
const selectedPool = await
|
|
6200
|
+
const selectedPool = await getPoolById(
|
|
6201
|
+
this.canisterContext,
|
|
6202
|
+
request.poolId
|
|
6203
|
+
);
|
|
5586
6204
|
const selectedAsset = selectedPool.asset;
|
|
5587
6205
|
const minimumBorrowAmountError = getBorrowAmountMinimumValidationError({
|
|
5588
6206
|
amount: request.amount,
|
|
@@ -5594,41 +6212,49 @@ var LendingModule = class {
|
|
|
5594
6212
|
minimumBorrowAmountError.message
|
|
5595
6213
|
);
|
|
5596
6214
|
}
|
|
5597
|
-
const
|
|
5598
|
-
|
|
6215
|
+
const receiver = parseOutflowDestination({
|
|
6216
|
+
destination,
|
|
5599
6217
|
asset: selectedAsset,
|
|
5600
|
-
|
|
6218
|
+
poolChain: selectedPool.chain,
|
|
6219
|
+
destinationChain: request.chain
|
|
5601
6220
|
});
|
|
5602
6221
|
const lendingActor = createLendingActor(this.canisterContext);
|
|
5603
6222
|
try {
|
|
5604
6223
|
const expiryTimestamp = computeExpiryTimestampFromNow();
|
|
5605
6224
|
const nonce = await lendingActor.get_nonce(signerAccount);
|
|
5606
|
-
const
|
|
6225
|
+
const borrowActionData = {
|
|
5607
6226
|
profileId: request.profileId,
|
|
5608
6227
|
poolId: request.poolId,
|
|
5609
6228
|
amount: request.amount,
|
|
5610
|
-
|
|
6229
|
+
chain: request.chain,
|
|
6230
|
+
receiver: {
|
|
6231
|
+
address: receiver.address,
|
|
6232
|
+
type: receiver.accountType
|
|
6233
|
+
},
|
|
5611
6234
|
signerWalletAddress: signerAccount,
|
|
5612
6235
|
expiryTimestamp
|
|
5613
6236
|
};
|
|
6237
|
+
const borrowSubmissionData = {
|
|
6238
|
+
...borrowActionData,
|
|
6239
|
+
receiverAccount: receiver.canisterAccount
|
|
6240
|
+
};
|
|
5614
6241
|
return {
|
|
5615
6242
|
kind: WalletActionKind.createBorrow,
|
|
5616
6243
|
executionKind: WalletExecutionKind.signMessage,
|
|
5617
6244
|
actionType: WalletActionKind.createBorrow,
|
|
5618
|
-
transferMode: TransferMode.native,
|
|
5619
6245
|
account: signerAccount,
|
|
5620
6246
|
message: createBorrowAssetMessage(
|
|
5621
6247
|
{
|
|
5622
6248
|
pool_id: request.poolId,
|
|
5623
6249
|
amount: request.amount.toString(),
|
|
5624
|
-
account:
|
|
6250
|
+
account: receiver.messageAccount,
|
|
5625
6251
|
expiry_timestamp: expiryTimestamp
|
|
5626
6252
|
},
|
|
5627
6253
|
nonce
|
|
5628
6254
|
),
|
|
5629
|
-
data:
|
|
6255
|
+
data: borrowActionData,
|
|
5630
6256
|
submit: async (signatureInfo) => {
|
|
5631
|
-
return await this.submitBorrow(
|
|
6257
|
+
return await this.submitBorrow(borrowSubmissionData, signatureInfo);
|
|
5632
6258
|
}
|
|
5633
6259
|
};
|
|
5634
6260
|
} catch (error) {
|
|
@@ -5645,7 +6271,7 @@ var LendingModule = class {
|
|
|
5645
6271
|
).borrow_assets(principal.Principal.fromText(request.profileId), {
|
|
5646
6272
|
data: {
|
|
5647
6273
|
expiry_timestamp: request.expiryTimestamp,
|
|
5648
|
-
account:
|
|
6274
|
+
account: request.receiverAccount,
|
|
5649
6275
|
pool_id: principal.Principal.fromText(request.poolId),
|
|
5650
6276
|
amount: request.amount
|
|
5651
6277
|
},
|
|
@@ -5763,11 +6389,18 @@ var LendingModule = class {
|
|
|
5763
6389
|
*
|
|
5764
6390
|
* ETH stablecoin deposit-address estimates are served by the deposit-address
|
|
5765
6391
|
* canister. BTC estimates include the ckBTC minter deposit fee and ledger fee.
|
|
6392
|
+
* ICP-chain estimates return the corresponding ICRC ledger fee.
|
|
5766
6393
|
*
|
|
5767
6394
|
* @param request - Asset and chain pair to estimate for.
|
|
5768
6395
|
* @returns Total fee estimate rounded up in the asset's base units.
|
|
5769
6396
|
*/
|
|
5770
6397
|
async estimateInflowFee(request) {
|
|
6398
|
+
if (request.chain === Chain.ICP) {
|
|
6399
|
+
const ledgerFee = await this.estimateIcrcLedgerFee(request);
|
|
6400
|
+
return {
|
|
6401
|
+
totalFee: roundInflowFeeEstimate(request, ledgerFee)
|
|
6402
|
+
};
|
|
6403
|
+
}
|
|
5771
6404
|
if (isEthStablecoin(request.asset, request.chain)) {
|
|
5772
6405
|
const result = await createDepositAccountsActor(
|
|
5773
6406
|
this.canisterContext
|
|
@@ -5797,6 +6430,14 @@ var LendingModule = class {
|
|
|
5797
6430
|
]);
|
|
5798
6431
|
return { totalFee: minterFee + ledgerFee };
|
|
5799
6432
|
}
|
|
6433
|
+
async estimateIcrcLedgerFee(request) {
|
|
6434
|
+
const route = getInflowFeeLedgerAssetRoute(request);
|
|
6435
|
+
return await createIcrcLedgerActor({
|
|
6436
|
+
canisterContext: this.canisterContext,
|
|
6437
|
+
canisterId: route.ledgerCanisterId,
|
|
6438
|
+
ledgerName: `${request.asset} ${request.chain}`
|
|
6439
|
+
}).icrc1_fee();
|
|
6440
|
+
}
|
|
5800
6441
|
/**
|
|
5801
6442
|
* Submits an inflow transaction id for faster indexing.
|
|
5802
6443
|
*
|
|
@@ -5806,6 +6447,12 @@ var LendingModule = class {
|
|
|
5806
6447
|
* @returns Acknowledgement including the submitted `txid`.
|
|
5807
6448
|
*/
|
|
5808
6449
|
async submitInflow(request) {
|
|
6450
|
+
if (request.chain !== void 0 && request.chain !== Chain.BTC && request.chain !== Chain.ETH) {
|
|
6451
|
+
throw new LiquidiumError(
|
|
6452
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
6453
|
+
`Inflow submission is not supported for ${String(request.chain)}`
|
|
6454
|
+
);
|
|
6455
|
+
}
|
|
5809
6456
|
const apiClient = this.requireApi();
|
|
5810
6457
|
const response = await apiClient.post(SdkApiPath.inflow, request);
|
|
5811
6458
|
return {
|
|
@@ -5845,30 +6492,39 @@ var LendingModule = class {
|
|
|
5845
6492
|
return new SupplyFlowExecutor({
|
|
5846
6493
|
canisterContext: this.canisterContext,
|
|
5847
6494
|
evmReadClient: this.evmReadClient,
|
|
5848
|
-
getPoolById: async (poolId) => await this.getPoolById(poolId),
|
|
5849
6495
|
requireApi: () => {
|
|
5850
6496
|
this.requireApi();
|
|
5851
6497
|
},
|
|
5852
6498
|
submitInflow: async (request) => await this.submitInflow(request)
|
|
5853
6499
|
});
|
|
5854
6500
|
}
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
6501
|
+
};
|
|
6502
|
+
function getInflowFeeLedgerAssetRoute(request) {
|
|
6503
|
+
if (request.chain !== Chain.ICP) {
|
|
6504
|
+
throw new LiquidiumError(
|
|
6505
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
6506
|
+
`IC ledger inflow fees are not supported for ${request.asset} on ${request.chain}`
|
|
5861
6507
|
);
|
|
5862
|
-
const decodedPool = selectedPool ? decodeFlexiblePool(selectedPool) : null;
|
|
5863
|
-
if (!decodedPool) {
|
|
5864
|
-
throw new LiquidiumError(
|
|
5865
|
-
LiquidiumErrorCode.POOL_NOT_FOUND,
|
|
5866
|
-
`Pool not found: ${poolId}`
|
|
5867
|
-
);
|
|
5868
|
-
}
|
|
5869
|
-
return decodedPool;
|
|
5870
6508
|
}
|
|
5871
|
-
|
|
6509
|
+
return getPoolLedgerAssetRoute(request);
|
|
6510
|
+
}
|
|
6511
|
+
function resolveOutflowDestinationInput(params) {
|
|
6512
|
+
const receiver = params.receiver;
|
|
6513
|
+
const address = typeof receiver === "string" ? receiver.trim() : receiver.address.trim();
|
|
6514
|
+
if (!address) {
|
|
6515
|
+
throw new LiquidiumError(
|
|
6516
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
6517
|
+
params.errorMessage
|
|
6518
|
+
);
|
|
6519
|
+
}
|
|
6520
|
+
if (typeof receiver === "string") {
|
|
6521
|
+
return address;
|
|
6522
|
+
}
|
|
6523
|
+
return {
|
|
6524
|
+
address,
|
|
6525
|
+
type: receiver.type
|
|
6526
|
+
};
|
|
6527
|
+
}
|
|
5872
6528
|
function mapExpectedOutflowDetails(details, expectedOutflowType, operation) {
|
|
5873
6529
|
if (details.outflowType !== expectedOutflowType) {
|
|
5874
6530
|
throw new LiquidiumError(
|
|
@@ -5962,6 +6618,12 @@ function formatPrice(price, decimals) {
|
|
|
5962
6618
|
|
|
5963
6619
|
// src/modules/market/market.ts
|
|
5964
6620
|
var ZERO_POOL_RATE = [0n, 0n, 0n];
|
|
6621
|
+
var BACKING_POOL_CHAIN_BY_ASSET = {
|
|
6622
|
+
[Asset.BTC]: Chain.BTC,
|
|
6623
|
+
[Asset.ICP]: Chain.ICP,
|
|
6624
|
+
[Asset.USDC]: Chain.ETH,
|
|
6625
|
+
[Asset.USDT]: Chain.ETH
|
|
6626
|
+
};
|
|
5965
6627
|
var MarketModule = class {
|
|
5966
6628
|
constructor(canisterContext) {
|
|
5967
6629
|
this.canisterContext = canisterContext;
|
|
@@ -6019,15 +6681,26 @@ var MarketModule = class {
|
|
|
6019
6681
|
}
|
|
6020
6682
|
}
|
|
6021
6683
|
/**
|
|
6022
|
-
* Resolves a single pool for the given
|
|
6684
|
+
* Resolves a single backing pool for the given Chain + Asset identifier.
|
|
6685
|
+
*
|
|
6686
|
+
* Native and chain-key identifiers share a pool. For example, both
|
|
6687
|
+
* `ETH/USDT` and `ICP/USDT` resolve to the USDT lending pool.
|
|
6023
6688
|
*
|
|
6024
6689
|
* @param query - The market asset and chain pair to match.
|
|
6025
6690
|
* @returns The single pool that matches the requested asset and chain.
|
|
6026
6691
|
*/
|
|
6027
6692
|
async findPool(query) {
|
|
6693
|
+
const identifier = { chain: query.chain, asset: query.asset };
|
|
6694
|
+
if (!isAssetIdentifier(identifier)) {
|
|
6695
|
+
throw new LiquidiumError(
|
|
6696
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
6697
|
+
`Unsupported asset identifier: ${identifier.chain}/${identifier.asset}`
|
|
6698
|
+
);
|
|
6699
|
+
}
|
|
6028
6700
|
const pools = await this.listPools();
|
|
6701
|
+
const backingPoolChain = BACKING_POOL_CHAIN_BY_ASSET[identifier.asset];
|
|
6029
6702
|
const matchedPools = pools.filter(
|
|
6030
|
-
(pool) => pool.asset ===
|
|
6703
|
+
(pool) => pool.asset === identifier.asset && pool.chain === backingPoolChain
|
|
6031
6704
|
);
|
|
6032
6705
|
if (matchedPools.length === 0) {
|
|
6033
6706
|
throw new LiquidiumError(
|
|
@@ -6457,8 +7130,10 @@ exports.Chain = Chain;
|
|
|
6457
7130
|
exports.Environment = Environment;
|
|
6458
7131
|
exports.EvmSupplyApprovalStrategy = EvmSupplyApprovalStrategy;
|
|
6459
7132
|
exports.HistoryModule = HistoryModule;
|
|
7133
|
+
exports.InstantLoanCreatedError = InstantLoanCreatedError;
|
|
6460
7134
|
exports.InstantLoansModule = InstantLoansModule;
|
|
6461
7135
|
exports.LendingModule = LendingModule;
|
|
7136
|
+
exports.LiquidiumAccountType = LiquidiumAccountType;
|
|
6462
7137
|
exports.LiquidiumClient = LiquidiumClient;
|
|
6463
7138
|
exports.LiquidiumError = LiquidiumError;
|
|
6464
7139
|
exports.LiquidiumErrorCode = LiquidiumErrorCode;
|
|
@@ -6474,7 +7149,6 @@ exports.RATE_DECIMALS = RATE_DECIMALS;
|
|
|
6474
7149
|
exports.RATE_SCALE = RATE_SCALE2;
|
|
6475
7150
|
exports.SupplyAction = SupplyAction;
|
|
6476
7151
|
exports.SupplyPlanType = SupplyPlanType;
|
|
6477
|
-
exports.TransferMode = TransferMode;
|
|
6478
7152
|
exports.USDC_CONTRACT_ADDRESS = USDC_CONTRACT_ADDRESS;
|
|
6479
7153
|
exports.USDT_CONTRACT_ADDRESS = USDT_CONTRACT_ADDRESS;
|
|
6480
7154
|
exports.WalletActionKind = WalletActionKind;
|
|
@@ -6484,6 +7158,7 @@ exports.executeWith = executeWith;
|
|
|
6484
7158
|
exports.getMinimumBorrowAmount = getMinimumBorrowAmount;
|
|
6485
7159
|
exports.getMinimumWithdrawAmount = getMinimumWithdrawAmount;
|
|
6486
7160
|
exports.intFromPublicId = intFromPublicId;
|
|
7161
|
+
exports.isAssetIdentifier = isAssetIdentifier;
|
|
6487
7162
|
exports.publicIdFromInt = publicIdFromInt;
|
|
6488
7163
|
//# sourceMappingURL=index.cjs.map
|
|
6489
7164
|
//# sourceMappingURL=index.cjs.map
|