@liquidium/client 0.2.0 → 0.3.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 +58 -11
- package/dist/index.cjs +302 -143
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +235 -113
- package/dist/index.d.ts +235 -113
- package/dist/index.js +301 -144
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1591,9 +1591,9 @@ function buildActivityStatusPath(request) {
|
|
|
1591
1591
|
request.id
|
|
1592
1592
|
)}/status?${query.toString()}`;
|
|
1593
1593
|
}
|
|
1594
|
-
function
|
|
1595
|
-
const query = new URLSearchParams({
|
|
1596
|
-
return `${INSTANT_LOANS}/
|
|
1594
|
+
function buildInstantLoanFindPath(request) {
|
|
1595
|
+
const query = new URLSearchParams({ query: request.query });
|
|
1596
|
+
return `${INSTANT_LOANS}/find?${query.toString()}`;
|
|
1597
1597
|
}
|
|
1598
1598
|
function buildInstantLoanCollateralHintPath(request) {
|
|
1599
1599
|
return `${INSTANT_LOANS}/${encodeURIComponent(
|
|
@@ -2222,6 +2222,41 @@ function mapHistoryStatusToApi(status) {
|
|
|
2222
2222
|
return status.toUpperCase();
|
|
2223
2223
|
}
|
|
2224
2224
|
|
|
2225
|
+
// src/core/utils/api-response-parsers.ts
|
|
2226
|
+
var MILLISECONDS_PER_SECOND2 = 1e3;
|
|
2227
|
+
function parseNonEmptyApiString(value, field) {
|
|
2228
|
+
if (!value) {
|
|
2229
|
+
throwInvalidApiResponseField(field);
|
|
2230
|
+
}
|
|
2231
|
+
return value;
|
|
2232
|
+
}
|
|
2233
|
+
function parseUnsignedApiBigint(value, field) {
|
|
2234
|
+
if (!value || !/^\d+$/.test(value)) {
|
|
2235
|
+
throwInvalidApiResponseField(field);
|
|
2236
|
+
}
|
|
2237
|
+
return BigInt(value);
|
|
2238
|
+
}
|
|
2239
|
+
function parseIsoApiTimestampToUnixSeconds(value, field) {
|
|
2240
|
+
const timestamp = parseNonEmptyApiString(value, field);
|
|
2241
|
+
const timestampMilliseconds = Date.parse(timestamp);
|
|
2242
|
+
if (!Number.isFinite(timestampMilliseconds)) {
|
|
2243
|
+
throwInvalidApiResponseField(field);
|
|
2244
|
+
}
|
|
2245
|
+
return BigInt(Math.floor(timestampMilliseconds / MILLISECONDS_PER_SECOND2));
|
|
2246
|
+
}
|
|
2247
|
+
function parseApiStringUnion(value, allowedValues, field) {
|
|
2248
|
+
if (value !== void 0 && allowedValues.includes(value)) {
|
|
2249
|
+
return value;
|
|
2250
|
+
}
|
|
2251
|
+
throwInvalidApiResponseField(field);
|
|
2252
|
+
}
|
|
2253
|
+
function throwInvalidApiResponseField(field) {
|
|
2254
|
+
throw new LiquidiumError(
|
|
2255
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
2256
|
+
`Invalid ${field.context} ${field.label}`
|
|
2257
|
+
);
|
|
2258
|
+
}
|
|
2259
|
+
|
|
2225
2260
|
// src/core/utils/asset-decimals.ts
|
|
2226
2261
|
var ASSET_NATIVE_DECIMALS = {
|
|
2227
2262
|
BTC: 8n,
|
|
@@ -3105,6 +3140,39 @@ function assertSupportsIcrcAccountInflowTarget(asset) {
|
|
|
3105
3140
|
);
|
|
3106
3141
|
}
|
|
3107
3142
|
|
|
3143
|
+
// src/core/borrow-minimums.ts
|
|
3144
|
+
var MIN_BORROW_AMOUNTS_BY_ASSET = {
|
|
3145
|
+
BTC: 5100n,
|
|
3146
|
+
// 5,100 sats = 0.000051 BTC
|
|
3147
|
+
USDC: 1000000n,
|
|
3148
|
+
// 1 USDC
|
|
3149
|
+
USDT: 1000000n
|
|
3150
|
+
// 1 USDT
|
|
3151
|
+
};
|
|
3152
|
+
function getMinimumBorrowAmount(asset) {
|
|
3153
|
+
if (!isMinimumBorrowAsset(asset)) {
|
|
3154
|
+
return 0n;
|
|
3155
|
+
}
|
|
3156
|
+
return MIN_BORROW_AMOUNTS_BY_ASSET[asset];
|
|
3157
|
+
}
|
|
3158
|
+
function getBorrowAmountMinimumValidationError(params) {
|
|
3159
|
+
const minimumAmount = getMinimumBorrowAmount(params.asset);
|
|
3160
|
+
if (minimumAmount <= 0n || params.amount >= minimumAmount) {
|
|
3161
|
+
return null;
|
|
3162
|
+
}
|
|
3163
|
+
return {
|
|
3164
|
+
asset: params.asset,
|
|
3165
|
+
minimumAmount,
|
|
3166
|
+
message: formatMinimumBorrowAmountMessage(params.asset, minimumAmount)
|
|
3167
|
+
};
|
|
3168
|
+
}
|
|
3169
|
+
function formatMinimumBorrowAmountMessage(asset, minimumAmount) {
|
|
3170
|
+
return `Borrow amount must be at least ${minimumAmount} base units for ${asset}`;
|
|
3171
|
+
}
|
|
3172
|
+
function isMinimumBorrowAsset(asset) {
|
|
3173
|
+
return Object.hasOwn(MIN_BORROW_AMOUNTS_BY_ASSET, asset);
|
|
3174
|
+
}
|
|
3175
|
+
|
|
3108
3176
|
// src/modules/quote/types.ts
|
|
3109
3177
|
var QuoteValidationErrorCode = /* @__PURE__ */ ((QuoteValidationErrorCode2) => {
|
|
3110
3178
|
QuoteValidationErrorCode2["INVALID_LTV"] = "INVALID_LTV";
|
|
@@ -3127,7 +3195,6 @@ var BASIS_POINTS_DENOMINATOR = 10000n;
|
|
|
3127
3195
|
var BPS_PER_PERCENT = 100n;
|
|
3128
3196
|
var MIN_LTV_BPS = 0n;
|
|
3129
3197
|
var HIGH_LTV_WARNING_THRESHOLD_BPS = 8000n;
|
|
3130
|
-
var MIN_BORROW_AMOUNT_BASE_UNITS = 5000n;
|
|
3131
3198
|
var INTERNAL_USD_DECIMAL_PLACES = 8;
|
|
3132
3199
|
var PRICE_SCALE_DECIMAL_PLACES = 8;
|
|
3133
3200
|
var QuoteModule = class {
|
|
@@ -3185,11 +3252,12 @@ var QuoteModule = class {
|
|
|
3185
3252
|
message: `Price not available for collateral asset: ${collateralPool.asset}`
|
|
3186
3253
|
});
|
|
3187
3254
|
}
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3255
|
+
const borrowAmountError = createBorrowAmountValidationError({
|
|
3256
|
+
amount: request.borrowAmount,
|
|
3257
|
+
asset: borrowPool.asset
|
|
3258
|
+
});
|
|
3259
|
+
if (borrowAmountError) {
|
|
3260
|
+
validationErrors.push(borrowAmountError);
|
|
3193
3261
|
}
|
|
3194
3262
|
if (request.collateralAmount <= 0n) {
|
|
3195
3263
|
validationErrors.push({
|
|
@@ -3311,16 +3379,12 @@ var QuoteModule = class {
|
|
|
3311
3379
|
message: `Price not available for collateral asset: ${collateralAsset}`
|
|
3312
3380
|
});
|
|
3313
3381
|
}
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
validationErrors.push({
|
|
3321
|
-
code: "BORROW_AMOUNT_TOO_LOW" /* BORROW_AMOUNT_TOO_LOW */,
|
|
3322
|
-
message: `Borrow amount must be at least ${MIN_BORROW_AMOUNT_BASE_UNITS} base units`
|
|
3323
|
-
});
|
|
3382
|
+
const borrowAmountError = createBorrowAmountValidationError({
|
|
3383
|
+
amount: borrowAmount,
|
|
3384
|
+
asset: borrowAsset
|
|
3385
|
+
});
|
|
3386
|
+
if (borrowAmountError) {
|
|
3387
|
+
validationErrors.push(borrowAmountError);
|
|
3324
3388
|
}
|
|
3325
3389
|
if (targetLtvBps <= MIN_LTV_BPS) {
|
|
3326
3390
|
validationErrors.push({
|
|
@@ -3443,6 +3507,22 @@ function createQuoteResult(params) {
|
|
|
3443
3507
|
warnings: params.warnings
|
|
3444
3508
|
};
|
|
3445
3509
|
}
|
|
3510
|
+
function createBorrowAmountValidationError(params) {
|
|
3511
|
+
if (params.amount <= 0n) {
|
|
3512
|
+
return {
|
|
3513
|
+
code: "BORROW_AMOUNT_TOO_LOW" /* BORROW_AMOUNT_TOO_LOW */,
|
|
3514
|
+
message: "Borrow amount must be greater than 0"
|
|
3515
|
+
};
|
|
3516
|
+
}
|
|
3517
|
+
const minimumBorrowAmountError = getBorrowAmountMinimumValidationError(params);
|
|
3518
|
+
if (!minimumBorrowAmountError) {
|
|
3519
|
+
return null;
|
|
3520
|
+
}
|
|
3521
|
+
return {
|
|
3522
|
+
code: "BORROW_AMOUNT_TOO_LOW" /* BORROW_AMOUNT_TOO_LOW */,
|
|
3523
|
+
message: minimumBorrowAmountError.message
|
|
3524
|
+
};
|
|
3525
|
+
}
|
|
3446
3526
|
function computeUsdInternalFromBaseUnits(params) {
|
|
3447
3527
|
const { amountBaseUnits, priceScaled, assetDecimalPlaces } = params;
|
|
3448
3528
|
const scaleDiff = INTERNAL_USD_DECIMAL_PLACES - PRICE_SCALE_DECIMAL_PLACES;
|
|
@@ -3568,6 +3648,14 @@ var RATE_SCALE2 = 10n ** 27n;
|
|
|
3568
3648
|
var SECONDS_PER_YEAR = 31536000n;
|
|
3569
3649
|
var ETH_STABLECOIN_INFLOW_FEE_FALLBACK = 1500000n;
|
|
3570
3650
|
var INSTANT_LOAN_MIN_SLIPPAGE_BUFFER_BPS = 200n;
|
|
3651
|
+
var INSTANT_LOAN_FIND_QUERY_MAX_LENGTH = 256;
|
|
3652
|
+
var INSTANT_LOAN_WIRE_CONTEXT = "instant loan";
|
|
3653
|
+
var INSTANT_LOAN_ASSETS = [
|
|
3654
|
+
Asset.BTC,
|
|
3655
|
+
Asset.SOL,
|
|
3656
|
+
Asset.USDC,
|
|
3657
|
+
Asset.USDT
|
|
3658
|
+
];
|
|
3571
3659
|
var InstantLoansModule = class {
|
|
3572
3660
|
constructor(canisterContext, apiClient, lending, positions) {
|
|
3573
3661
|
this.canisterContext = canisterContext;
|
|
@@ -3624,7 +3712,19 @@ var InstantLoansModule = class {
|
|
|
3624
3712
|
borrowDestination,
|
|
3625
3713
|
refundDestination
|
|
3626
3714
|
});
|
|
3627
|
-
|
|
3715
|
+
const loanId = parseUnsignedApiBigint(response.loan.loanId, {
|
|
3716
|
+
context: INSTANT_LOAN_WIRE_CONTEXT,
|
|
3717
|
+
label: "loan ID"
|
|
3718
|
+
});
|
|
3719
|
+
const collateralAmount = parseUnsignedApiBigint(
|
|
3720
|
+
response.loan.collateral.amountHint,
|
|
3721
|
+
{
|
|
3722
|
+
context: INSTANT_LOAN_WIRE_CONTEXT,
|
|
3723
|
+
label: "collateral amount"
|
|
3724
|
+
}
|
|
3725
|
+
);
|
|
3726
|
+
const record = await this.getLoanRecord(loanId);
|
|
3727
|
+
return await this.mapLoanRecord(record, collateralAmount);
|
|
3628
3728
|
}
|
|
3629
3729
|
/**
|
|
3630
3730
|
* Resolves canonical canister state by loan id or short reference.
|
|
@@ -3637,21 +3737,30 @@ var InstantLoansModule = class {
|
|
|
3637
3737
|
*/
|
|
3638
3738
|
async get(request) {
|
|
3639
3739
|
const loanId = "loanId" in request ? request.loanId : decodeRef(request.ref);
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3740
|
+
const record = await this.getLoanRecord(loanId);
|
|
3741
|
+
const collateralAmount = await this.getCollateralAmountHint(loanId);
|
|
3742
|
+
return await this.mapLoanRecord(record, collateralAmount);
|
|
3743
|
+
}
|
|
3744
|
+
/**
|
|
3745
|
+
* Finds instant loans by short reference, numeric loan id string, address, or transaction id.
|
|
3746
|
+
*
|
|
3747
|
+
* Search returns lightweight matches. Call `get({ loanId })` or `get({ ref })`
|
|
3748
|
+
* when the user selects a match and you need hydrated loan state.
|
|
3749
|
+
*
|
|
3750
|
+
* @param query - Short reference, address, transaction id/hash, or numeric loan id string.
|
|
3751
|
+
* @returns Matching loan ids and references from the search index.
|
|
3752
|
+
*/
|
|
3753
|
+
async find(query) {
|
|
3754
|
+
const validatedQuery = validateInstantLoanFindQuery(query);
|
|
3755
|
+
const candidates = await this.findCandidateLoansByQuery(validatedQuery);
|
|
3756
|
+
return uniqueInstantLoanFindCandidates(candidates).map((candidate) => ({
|
|
3757
|
+
loanId: candidate.loanId,
|
|
3758
|
+
ref: candidate.ref,
|
|
3759
|
+
createdAt: candidate.createdAt,
|
|
3760
|
+
collateral: candidate.collateral,
|
|
3761
|
+
borrow: candidate.borrow,
|
|
3762
|
+
profileId: candidate.profileId
|
|
3763
|
+
}));
|
|
3655
3764
|
}
|
|
3656
3765
|
/**
|
|
3657
3766
|
* Returns the active instant-loans canister config via direct query.
|
|
@@ -3749,28 +3858,29 @@ var InstantLoansModule = class {
|
|
|
3749
3858
|
throw mapCanisterCallErrorToLiquidiumError("list_warmed_profiles", error);
|
|
3750
3859
|
}
|
|
3751
3860
|
}
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
* refund address but not the loan reference.
|
|
3758
|
-
*
|
|
3759
|
-
* @param address - Borrow or refund address to search for.
|
|
3760
|
-
* @returns Lightweight loan candidates associated with the address.
|
|
3761
|
-
*/
|
|
3762
|
-
async findByAddress(address) {
|
|
3763
|
-
const trimmedAddress = address.trim();
|
|
3764
|
-
if (!trimmedAddress) {
|
|
3765
|
-
throw new LiquidiumError(
|
|
3766
|
-
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
3767
|
-
"Address lookup requires a non-empty address"
|
|
3768
|
-
);
|
|
3769
|
-
}
|
|
3770
|
-
const apiClient = this.requireApi("Instant loan address lookup");
|
|
3771
|
-
const response = await apiClient.get(buildInstantLoanAddressLookupPath({ address: trimmedAddress }));
|
|
3861
|
+
async findCandidateLoansByQuery(query) {
|
|
3862
|
+
const apiClient = this.requireApi("Instant loan find");
|
|
3863
|
+
const response = await apiClient.get(
|
|
3864
|
+
buildInstantLoanFindPath({ query })
|
|
3865
|
+
);
|
|
3772
3866
|
return (response.candidates ?? response.loans ?? []).map(mapCandidateWire);
|
|
3773
3867
|
}
|
|
3868
|
+
async getLoanRecord(loanId) {
|
|
3869
|
+
try {
|
|
3870
|
+
const result = await createInstantLoansActor(
|
|
3871
|
+
this.canisterContext
|
|
3872
|
+
).get_loan(loanId);
|
|
3873
|
+
if ("Err" in result) {
|
|
3874
|
+
throw mapInstantLoansErrorToLiquidiumError(result.Err);
|
|
3875
|
+
}
|
|
3876
|
+
return result.Ok;
|
|
3877
|
+
} catch (error) {
|
|
3878
|
+
if (error instanceof LiquidiumError) {
|
|
3879
|
+
throw error;
|
|
3880
|
+
}
|
|
3881
|
+
throw mapCanisterCallErrorToLiquidiumError("get_loan", error);
|
|
3882
|
+
}
|
|
3883
|
+
}
|
|
3774
3884
|
async mapLoanRecord(record, collateralAmount) {
|
|
3775
3885
|
return await this.hydrateLoan({
|
|
3776
3886
|
loanId: record.id,
|
|
@@ -3784,35 +3894,22 @@ var InstantLoansModule = class {
|
|
|
3784
3894
|
borrowAsset: getVariantKey(record.borrow_asset),
|
|
3785
3895
|
borrowAmount: record.borrow_amount,
|
|
3786
3896
|
borrowDestination: accountFromCanister(record.borrow_destination),
|
|
3787
|
-
refundDestination: accountFromCanister(record.refund_destination)
|
|
3897
|
+
refundDestination: accountFromCanister(record.refund_destination),
|
|
3898
|
+
depositDetectedTimestamp: record.deposit_detected_ts[0] ?? null,
|
|
3899
|
+
expiryTimestamp: record.expires_at[0] ?? deriveDepositExpiryTimestamp({
|
|
3900
|
+
depositDetectedTimestamp: record.deposit_detected_ts[0] ?? null,
|
|
3901
|
+
depositWindowSeconds: record.ltv_timer_s
|
|
3902
|
+
})
|
|
3788
3903
|
});
|
|
3789
3904
|
}
|
|
3790
3905
|
async getCollateralAmountHint(loanId) {
|
|
3791
|
-
const apiClient = this.requireApi("Instant loan
|
|
3792
|
-
const response = await apiClient.get(
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
loanId,
|
|
3799
|
-
profileId: loan.profileId,
|
|
3800
|
-
ltvMaxBps: parseBigintWire(loan.ltvMaxBps, "max LTV"),
|
|
3801
|
-
depositWindowSeconds: parseBigintWire(
|
|
3802
|
-
loan.depositWindowSeconds,
|
|
3803
|
-
"deposit window"
|
|
3804
|
-
),
|
|
3805
|
-
collateralPoolId: loan.collateral.poolId,
|
|
3806
|
-
collateralAmount: parseBigintWire(
|
|
3807
|
-
loan.collateral.amountHint,
|
|
3808
|
-
"collateral amount"
|
|
3809
|
-
),
|
|
3810
|
-
borrowPoolId: loan.borrow.poolId,
|
|
3811
|
-
collateralAsset: loan.collateral.asset,
|
|
3812
|
-
borrowAsset: loan.borrow.asset,
|
|
3813
|
-
borrowAmount: parseBigintWire(loan.borrow.amount, "borrow amount"),
|
|
3814
|
-
borrowDestination: accountFromWire(loan.borrow.destination),
|
|
3815
|
-
refundDestination: accountFromWire(loan.refundDestination)
|
|
3906
|
+
const apiClient = this.requireApi("Instant loan collateral hint");
|
|
3907
|
+
const response = await apiClient.get(
|
|
3908
|
+
buildInstantLoanCollateralHintPath({ loanId })
|
|
3909
|
+
);
|
|
3910
|
+
return parseUnsignedApiBigint(response.collateralAmountHint, {
|
|
3911
|
+
context: INSTANT_LOAN_WIRE_CONTEXT,
|
|
3912
|
+
label: "collateral amount"
|
|
3816
3913
|
});
|
|
3817
3914
|
}
|
|
3818
3915
|
async hydrateLoan(input) {
|
|
@@ -3866,7 +3963,9 @@ var InstantLoansModule = class {
|
|
|
3866
3963
|
collateralAmount,
|
|
3867
3964
|
decimals: collateralDecimals,
|
|
3868
3965
|
asset: collateralAsset,
|
|
3869
|
-
target: depositTarget
|
|
3966
|
+
target: depositTarget,
|
|
3967
|
+
detectedTimestamp: input.depositDetectedTimestamp,
|
|
3968
|
+
expiryTimestamp: input.expiryTimestamp
|
|
3870
3969
|
});
|
|
3871
3970
|
const repayment = {
|
|
3872
3971
|
amount: repaymentAmount,
|
|
@@ -3930,7 +4029,9 @@ var InstantLoansModule = class {
|
|
|
3930
4029
|
inflowFeeAmount: inflowFee.totalFee,
|
|
3931
4030
|
asset: input.asset,
|
|
3932
4031
|
chain: input.target.chain,
|
|
3933
|
-
target: input.target
|
|
4032
|
+
target: input.target,
|
|
4033
|
+
detectedTimestamp: input.detectedTimestamp,
|
|
4034
|
+
expiryTimestamp: input.expiryTimestamp
|
|
3934
4035
|
};
|
|
3935
4036
|
}
|
|
3936
4037
|
async estimateRepaymentInflowFee(asset, chain) {
|
|
@@ -4026,6 +4127,12 @@ function deriveInstantLoanStatus(input) {
|
|
|
4026
4127
|
}
|
|
4027
4128
|
return InstantLoanStatus.awaitingDeposit;
|
|
4028
4129
|
}
|
|
4130
|
+
function deriveDepositExpiryTimestamp(input) {
|
|
4131
|
+
if (input.depositDetectedTimestamp === null) {
|
|
4132
|
+
return null;
|
|
4133
|
+
}
|
|
4134
|
+
return input.depositDetectedTimestamp + input.depositWindowSeconds;
|
|
4135
|
+
}
|
|
4029
4136
|
function validateCreateRequest(request) {
|
|
4030
4137
|
if (request.collateralAmount <= 0n) {
|
|
4031
4138
|
throw new LiquidiumError(
|
|
@@ -4074,18 +4181,6 @@ function accountFromCanister(account) {
|
|
|
4074
4181
|
}
|
|
4075
4182
|
return { type: "External", address: account.External };
|
|
4076
4183
|
}
|
|
4077
|
-
function accountFromWire(account) {
|
|
4078
|
-
if ("Native" in account) {
|
|
4079
|
-
return { type: "Native", principal: account.Native };
|
|
4080
|
-
}
|
|
4081
|
-
if ("External" in account) {
|
|
4082
|
-
return { type: "External", address: account.External };
|
|
4083
|
-
}
|
|
4084
|
-
if (account.type === "Native") {
|
|
4085
|
-
return { type: "Native", principal: account.principal };
|
|
4086
|
-
}
|
|
4087
|
-
return { type: "External", address: account.address };
|
|
4088
|
-
}
|
|
4089
4184
|
function mapInstantLoanEvent(event) {
|
|
4090
4185
|
return {
|
|
4091
4186
|
id: event.id,
|
|
@@ -4204,55 +4299,80 @@ function decodeRef(ref) {
|
|
|
4204
4299
|
);
|
|
4205
4300
|
}
|
|
4206
4301
|
}
|
|
4207
|
-
function
|
|
4208
|
-
|
|
4209
|
-
const ref = wire.ref ?? wire.short_ref ?? publicIdFromInt(loanId);
|
|
4210
|
-
const createdAt = wire.createdAt ?? wire.created_at;
|
|
4211
|
-
return {
|
|
4212
|
-
loanId,
|
|
4213
|
-
ref,
|
|
4214
|
-
profileId: requiredString(
|
|
4215
|
-
wire.profileId ?? wire.lending_profile,
|
|
4216
|
-
"profile ID"
|
|
4217
|
-
),
|
|
4218
|
-
...createdAt ? { createdAt: new Date(createdAt) } : {},
|
|
4219
|
-
collateralPoolId: requiredString(
|
|
4220
|
-
wire.collateralPoolId ?? wire.lend_pool_ic_id,
|
|
4221
|
-
"collateral pool ID"
|
|
4222
|
-
),
|
|
4223
|
-
borrowPoolId: requiredString(
|
|
4224
|
-
wire.borrowPoolId ?? wire.borrow_pool_ic_id,
|
|
4225
|
-
"borrow pool ID"
|
|
4226
|
-
),
|
|
4227
|
-
collateralAsset: requiredString(
|
|
4228
|
-
wire.collateralAsset ?? wire.lend_asset,
|
|
4229
|
-
"collateral asset"
|
|
4230
|
-
),
|
|
4231
|
-
borrowAsset: requiredString(
|
|
4232
|
-
wire.borrowAsset ?? wire.borrow_asset,
|
|
4233
|
-
"borrow asset"
|
|
4234
|
-
),
|
|
4235
|
-
collateralAmount: parseBigintWire(
|
|
4236
|
-
wire.collateralAmount,
|
|
4237
|
-
"collateral amount"
|
|
4238
|
-
)
|
|
4239
|
-
};
|
|
4240
|
-
}
|
|
4241
|
-
function parseBigintWire(value, label) {
|
|
4242
|
-
if (!value || !/^\d+$/.test(value)) {
|
|
4302
|
+
function validateInstantLoanFindQuery(query) {
|
|
4303
|
+
if (typeof query !== "string") {
|
|
4243
4304
|
throw new LiquidiumError(
|
|
4244
4305
|
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
4245
|
-
|
|
4306
|
+
"Instant loan find query must be a string"
|
|
4246
4307
|
);
|
|
4247
4308
|
}
|
|
4248
|
-
|
|
4309
|
+
const trimmedQuery = query.trim();
|
|
4310
|
+
if (!trimmedQuery) {
|
|
4311
|
+
throw new LiquidiumError(
|
|
4312
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
4313
|
+
"Instant loan find query must be non-empty"
|
|
4314
|
+
);
|
|
4315
|
+
}
|
|
4316
|
+
if (trimmedQuery.length > INSTANT_LOAN_FIND_QUERY_MAX_LENGTH) {
|
|
4317
|
+
throw new LiquidiumError(
|
|
4318
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
4319
|
+
`Instant loan find query must be at most ${INSTANT_LOAN_FIND_QUERY_MAX_LENGTH.toString()} characters`
|
|
4320
|
+
);
|
|
4321
|
+
}
|
|
4322
|
+
return trimmedQuery;
|
|
4249
4323
|
}
|
|
4250
|
-
function
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4324
|
+
function uniqueInstantLoanFindCandidates(candidates) {
|
|
4325
|
+
const candidatesByLoanId = /* @__PURE__ */ new Map();
|
|
4326
|
+
for (const candidate of candidates) {
|
|
4327
|
+
if (!candidatesByLoanId.has(candidate.loanId)) {
|
|
4328
|
+
candidatesByLoanId.set(candidate.loanId, candidate);
|
|
4329
|
+
}
|
|
4330
|
+
}
|
|
4331
|
+
return [...candidatesByLoanId.values()];
|
|
4332
|
+
}
|
|
4333
|
+
function mapCandidateWire(wire) {
|
|
4334
|
+
return {
|
|
4335
|
+
loanId: parseUnsignedApiBigint(wire.loan_id, {
|
|
4336
|
+
context: INSTANT_LOAN_WIRE_CONTEXT,
|
|
4337
|
+
label: "loan ID"
|
|
4338
|
+
}),
|
|
4339
|
+
ref: parseNonEmptyApiString(wire.short_ref, {
|
|
4340
|
+
context: INSTANT_LOAN_WIRE_CONTEXT,
|
|
4341
|
+
label: "short reference"
|
|
4342
|
+
}),
|
|
4343
|
+
createdAt: parseIsoApiTimestampToUnixSeconds(wire.created_at, {
|
|
4344
|
+
context: INSTANT_LOAN_WIRE_CONTEXT,
|
|
4345
|
+
label: "creation timestamp"
|
|
4346
|
+
}),
|
|
4347
|
+
collateral: {
|
|
4348
|
+
poolId: parseNonEmptyApiString(wire.lend_pool_ic_id, {
|
|
4349
|
+
context: INSTANT_LOAN_WIRE_CONTEXT,
|
|
4350
|
+
label: "lend pool ID"
|
|
4351
|
+
}),
|
|
4352
|
+
asset: parseApiStringUnion(wire.lend_asset, INSTANT_LOAN_ASSETS, {
|
|
4353
|
+
context: INSTANT_LOAN_WIRE_CONTEXT,
|
|
4354
|
+
label: "lend asset"
|
|
4355
|
+
}),
|
|
4356
|
+
amount: parseUnsignedApiBigint(wire.collateral_amount, {
|
|
4357
|
+
context: INSTANT_LOAN_WIRE_CONTEXT,
|
|
4358
|
+
label: "collateral amount"
|
|
4359
|
+
})
|
|
4360
|
+
},
|
|
4361
|
+
borrow: {
|
|
4362
|
+
poolId: parseNonEmptyApiString(wire.borrow_pool_ic_id, {
|
|
4363
|
+
context: INSTANT_LOAN_WIRE_CONTEXT,
|
|
4364
|
+
label: "borrow pool ID"
|
|
4365
|
+
}),
|
|
4366
|
+
asset: parseApiStringUnion(wire.borrow_asset, INSTANT_LOAN_ASSETS, {
|
|
4367
|
+
context: INSTANT_LOAN_WIRE_CONTEXT,
|
|
4368
|
+
label: "borrow asset"
|
|
4369
|
+
})
|
|
4370
|
+
},
|
|
4371
|
+
profileId: parseNonEmptyApiString(wire.profile, {
|
|
4372
|
+
context: INSTANT_LOAN_WIRE_CONTEXT,
|
|
4373
|
+
label: "profile ID"
|
|
4374
|
+
})
|
|
4375
|
+
};
|
|
4256
4376
|
}
|
|
4257
4377
|
function mapInstantLoansErrorToLiquidiumError(error) {
|
|
4258
4378
|
const [key, payload] = Object.entries(error)[0];
|
|
@@ -4713,9 +4833,28 @@ var LendingModule = class {
|
|
|
4713
4833
|
"Borrow requires a signer account"
|
|
4714
4834
|
);
|
|
4715
4835
|
}
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4836
|
+
if (request.amount <= 0n) {
|
|
4837
|
+
throw new LiquidiumError(
|
|
4838
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
4839
|
+
"Borrow amount must be greater than 0"
|
|
4840
|
+
);
|
|
4841
|
+
}
|
|
4842
|
+
const selectedPool = await this.getPoolById(request.poolId);
|
|
4843
|
+
const selectedAsset = getVariantKey(selectedPool.asset);
|
|
4844
|
+
const minimumBorrowAmountError = getBorrowAmountMinimumValidationError({
|
|
4845
|
+
amount: request.amount,
|
|
4846
|
+
asset: selectedAsset
|
|
4847
|
+
});
|
|
4848
|
+
if (minimumBorrowAmountError) {
|
|
4849
|
+
throw new LiquidiumError(
|
|
4850
|
+
LiquidiumErrorCode.VALIDATION_ERROR,
|
|
4851
|
+
minimumBorrowAmountError.message
|
|
4852
|
+
);
|
|
4853
|
+
}
|
|
4854
|
+
const receiverAddress = normalizeExternalAddress({
|
|
4855
|
+
address: destinationAccount,
|
|
4856
|
+
asset: selectedAsset,
|
|
4857
|
+
chain: getVariantKey(selectedPool.chain)
|
|
4719
4858
|
});
|
|
4720
4859
|
const lendingActor = createLendingActor(this.canisterContext);
|
|
4721
4860
|
try {
|
|
@@ -5838,7 +5977,7 @@ var PositionsModule = class {
|
|
|
5838
5977
|
pool,
|
|
5839
5978
|
priceUsd,
|
|
5840
5979
|
suppliedUsd: nativeAmountToUsdScaled(
|
|
5841
|
-
position.deposited
|
|
5980
|
+
position.deposited,
|
|
5842
5981
|
position.depositedDecimals,
|
|
5843
5982
|
priceUsd
|
|
5844
5983
|
),
|
|
@@ -5873,6 +6012,24 @@ var PositionsModule = class {
|
|
|
5873
6012
|
const buffered = rawDebt * (BPS_SCALE + bufferBps) / BPS_SCALE;
|
|
5874
6013
|
return { amount: buffered, decimals: position.borrowedDecimals };
|
|
5875
6014
|
}
|
|
6015
|
+
/**
|
|
6016
|
+
* Returns the current full withdraw amount for a position.
|
|
6017
|
+
*
|
|
6018
|
+
* `Position.deposited` already reflects the current supplied balance at the
|
|
6019
|
+
* latest lending index; do not add `earnedInterest` to this amount.
|
|
6020
|
+
* Pass `amount` to withdraw calls and use `decimals` for display formatting.
|
|
6021
|
+
*
|
|
6022
|
+
* @param profileId - The Liquidium profile principal text.
|
|
6023
|
+
* @param poolId - The pool principal text.
|
|
6024
|
+
* @returns Full withdraw amount in the supplied asset's base units.
|
|
6025
|
+
*/
|
|
6026
|
+
async getFullWithdrawAmount(profileId, poolId) {
|
|
6027
|
+
const position = await this.getPosition(profileId, poolId);
|
|
6028
|
+
if (!position) {
|
|
6029
|
+
return { amount: 0n, decimals: 0n };
|
|
6030
|
+
}
|
|
6031
|
+
return { amount: position.deposited, decimals: position.depositedDecimals };
|
|
6032
|
+
}
|
|
5876
6033
|
};
|
|
5877
6034
|
function nativeAmountToUsdScaled(amount, nativeDecimals, priceUsd) {
|
|
5878
6035
|
if (amount <= 0n || priceUsd <= 0) {
|
|
@@ -5964,6 +6121,6 @@ function resolveEvmReadClient(config) {
|
|
|
5964
6121
|
});
|
|
5965
6122
|
}
|
|
5966
6123
|
|
|
5967
|
-
export { AccountsModule, ActivitiesModule, ActivityDirection, ActivityFilter, ActivityKind, ActivityStatus, Asset, CK_ETH_DEPOSIT_CONTRACT_ADDRESS, Chain, Environment, EvmSupplyApprovalStrategy, HistoryModule, InflowSubmitType, InstantLoanStatus, InstantLoansModule, LendingModule, LiquidiumClient, LiquidiumError, LiquidiumErrorCode, MarketModule, OutflowType, PositionsModule, QuoteModule, QuoteValidationErrorCode, QuoteWarningCode, RATE_DECIMALS, RATE_SCALE, SupplyAction, SupplyPlanType, TransferMode, USDC_CONTRACT_ADDRESS, USDT_CONTRACT_ADDRESS, UserHistoryStatus, WalletExecutionKind, createTransferErc20Transaction, executeWith, intFromPublicId, publicIdFromInt };
|
|
6124
|
+
export { AccountsModule, ActivitiesModule, ActivityDirection, ActivityFilter, ActivityKind, ActivityStatus, Asset, CK_ETH_DEPOSIT_CONTRACT_ADDRESS, Chain, Environment, EvmSupplyApprovalStrategy, HistoryModule, InflowSubmitType, InstantLoanStatus, InstantLoansModule, LendingModule, LiquidiumClient, LiquidiumError, LiquidiumErrorCode, MIN_BORROW_AMOUNTS_BY_ASSET, MarketModule, OutflowType, PositionsModule, QuoteModule, QuoteValidationErrorCode, QuoteWarningCode, RATE_DECIMALS, RATE_SCALE, SupplyAction, SupplyPlanType, TransferMode, USDC_CONTRACT_ADDRESS, USDT_CONTRACT_ADDRESS, UserHistoryStatus, WalletExecutionKind, createTransferErc20Transaction, executeWith, getMinimumBorrowAmount, intFromPublicId, publicIdFromInt };
|
|
5968
6125
|
//# sourceMappingURL=index.js.map
|
|
5969
6126
|
//# sourceMappingURL=index.js.map
|