@kamino-finance/klend-sdk 5.0.1 → 5.0.2-fix
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/classes/obligation.d.ts +3 -4
- package/dist/classes/obligation.d.ts.map +1 -1
- package/dist/classes/obligation.js +94 -26
- package/dist/classes/obligation.js.map +1 -1
- package/dist/classes/reserve.d.ts +2 -1
- package/dist/classes/reserve.d.ts.map +1 -1
- package/dist/classes/reserve.js +17 -5
- package/dist/classes/reserve.js.map +1 -1
- package/dist/lending_operations/repay_with_collateral_calcs.d.ts.map +1 -1
- package/dist/lending_operations/repay_with_collateral_calcs.js +5 -1
- package/dist/lending_operations/repay_with_collateral_calcs.js.map +1 -1
- package/dist/lending_operations/repay_with_collateral_operations.d.ts.map +1 -1
- package/dist/lending_operations/repay_with_collateral_operations.js +5 -1
- package/dist/lending_operations/repay_with_collateral_operations.js.map +1 -1
- package/package.json +1 -1
- package/src/classes/obligation.ts +139 -29
- package/src/classes/reserve.ts +31 -5
- package/src/lending_operations/repay_with_collateral_calcs.ts +5 -1
- package/src/lending_operations/repay_with_collateral_operations.ts +5 -1
|
@@ -362,6 +362,9 @@ export class KaminoObligation {
|
|
|
362
362
|
collateralExchangeRates: Map<PublicKey, Decimal>
|
|
363
363
|
): ObligationCollateral[] {
|
|
364
364
|
const newDeposits: ObligationCollateral[] = [];
|
|
365
|
+
const depositIndex = obligationDeposits.findIndex((deposit) => deposit.depositReserve.equals(changeReserve));
|
|
366
|
+
|
|
367
|
+
// Always copy the previous deposits and modify the changeReserve one if it exists
|
|
365
368
|
for (let i = 0; i < obligationDeposits.length; i++) {
|
|
366
369
|
if (obligationDeposits[i].depositReserve.equals(changeReserve)) {
|
|
367
370
|
const coll: ObligationCollateralFields = { ...obligationDeposits[i] };
|
|
@@ -375,6 +378,25 @@ export class KaminoObligation {
|
|
|
375
378
|
}
|
|
376
379
|
}
|
|
377
380
|
|
|
381
|
+
if (depositIndex === -1) {
|
|
382
|
+
// If the reserve is not in the obligation, we add it
|
|
383
|
+
const firstBorrowIndexAvailable = obligationDeposits.findIndex((deposit) =>
|
|
384
|
+
deposit.depositReserve.equals(PublicKey.default)
|
|
385
|
+
);
|
|
386
|
+
|
|
387
|
+
if (firstBorrowIndexAvailable === -1) {
|
|
388
|
+
throw new Error('No available borrows to modify');
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const coll: ObligationCollateralFields = { ...obligationDeposits[firstBorrowIndexAvailable] };
|
|
392
|
+
const exchangeRate = collateralExchangeRates.get(changeReserve)!;
|
|
393
|
+
const changeInCollateral = new Decimal(changeInLamports).mul(exchangeRate).toFixed(0);
|
|
394
|
+
coll.depositedAmount = new BN(positiveOrZero(new Decimal(changeInCollateral)).toString());
|
|
395
|
+
coll.depositReserve = changeReserve;
|
|
396
|
+
|
|
397
|
+
newDeposits[firstBorrowIndexAvailable] = new ObligationCollateral(coll);
|
|
398
|
+
}
|
|
399
|
+
|
|
378
400
|
return newDeposits;
|
|
379
401
|
}
|
|
380
402
|
|
|
@@ -387,17 +409,30 @@ export class KaminoObligation {
|
|
|
387
409
|
const newBorrows: ObligationLiquidity[] = [];
|
|
388
410
|
const borrowIndex = obligationBorrows.findIndex((borrow) => borrow.borrowReserve.equals(changeReserve));
|
|
389
411
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
412
|
+
// Always copy the previous borrows and modify the changeReserve one if it exists
|
|
413
|
+
for (let i = 0; i < obligationBorrows.length; i++) {
|
|
414
|
+
if (obligationBorrows[i].borrowReserve.equals(changeReserve)) {
|
|
415
|
+
const borrow: ObligationLiquidityFields = { ...obligationBorrows[borrowIndex] };
|
|
416
|
+
const newBorrowedAmount: Decimal = new Fraction(borrow.borrowedAmountSf).toDecimal().add(changeInLamports);
|
|
417
|
+
const newBorrowedAmountSf = Fraction.fromDecimal(positiveOrZero(newBorrowedAmount)).getValue();
|
|
418
|
+
borrow.borrowedAmountSf = newBorrowedAmountSf;
|
|
419
|
+
|
|
420
|
+
newBorrows.push(new ObligationLiquidity(borrow));
|
|
421
|
+
} else {
|
|
422
|
+
newBorrows.push(obligationBorrows[i]);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
if (borrowIndex === -1) {
|
|
427
|
+
// If the reserve is not in the obligation, we add it
|
|
397
428
|
const firstBorrowIndexAvailable = obligationBorrows.findIndex((borrow) =>
|
|
398
429
|
borrow.borrowReserve.equals(PublicKey.default)
|
|
399
430
|
);
|
|
400
431
|
|
|
432
|
+
if (firstBorrowIndexAvailable === -1) {
|
|
433
|
+
throw new Error('No available borrows to modify');
|
|
434
|
+
}
|
|
435
|
+
|
|
401
436
|
const borrow: ObligationLiquidityFields = { ...obligationBorrows[firstBorrowIndexAvailable] };
|
|
402
437
|
borrow.borrowedAmountSf = Fraction.fromDecimal(new Decimal(changeInLamports)).getValue();
|
|
403
438
|
borrow.borrowReserve = changeReserve;
|
|
@@ -405,7 +440,7 @@ export class KaminoObligation {
|
|
|
405
440
|
padding: [],
|
|
406
441
|
value: [Fraction.fromDecimal(cumulativeBorrowRate).getValue(), new BN(0), new BN(0), new BN(0)],
|
|
407
442
|
};
|
|
408
|
-
newBorrows
|
|
443
|
+
newBorrows[firstBorrowIndexAvailable] = new ObligationLiquidity(borrow);
|
|
409
444
|
}
|
|
410
445
|
|
|
411
446
|
return newBorrows;
|
|
@@ -433,7 +468,23 @@ export class KaminoObligation {
|
|
|
433
468
|
const { amountCollateral, amountDebt, action, mintCollateral, mintDebt, market } = params;
|
|
434
469
|
let newStats = { ...this.refreshedStats };
|
|
435
470
|
|
|
436
|
-
const
|
|
471
|
+
const collateralReservePk = mintCollateral ? market.getReserveByMint(mintCollateral)!.address : undefined;
|
|
472
|
+
const debtReservePk = mintDebt ? market.getReserveByMint(mintDebt)!.address : undefined;
|
|
473
|
+
|
|
474
|
+
const additionalReserves = [];
|
|
475
|
+
if (collateralReservePk !== undefined) {
|
|
476
|
+
additionalReserves.push(collateralReservePk);
|
|
477
|
+
}
|
|
478
|
+
if (debtReservePk !== undefined) {
|
|
479
|
+
additionalReserves.push(debtReservePk);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
const { collateralExchangeRates } = KaminoObligation.getRatesForObligation(
|
|
483
|
+
market,
|
|
484
|
+
this.state,
|
|
485
|
+
params.slot,
|
|
486
|
+
additionalReserves
|
|
487
|
+
);
|
|
437
488
|
|
|
438
489
|
const elevationGroup = params.elevationGroupOverride ?? this.state.elevationGroup;
|
|
439
490
|
|
|
@@ -444,8 +495,6 @@ export class KaminoObligation {
|
|
|
444
495
|
// so we have to recalculate the entire position, not just an updated deposit or borrow
|
|
445
496
|
// as both LTVs and borrow factors can change, affecting all calcs
|
|
446
497
|
|
|
447
|
-
const collateralReservePk = mintCollateral ? market.getReserveByMint(mintCollateral)!.address : undefined;
|
|
448
|
-
const debtReservePk = mintDebt ? market.getReserveByMint(mintDebt)!.address : undefined;
|
|
449
498
|
const debtReserveCumulativeBorrowRate = mintDebt
|
|
450
499
|
? market.getReserveByMint(mintDebt)!.getCumulativeBorrowRate()
|
|
451
500
|
: undefined;
|
|
@@ -453,6 +502,14 @@ export class KaminoObligation {
|
|
|
453
502
|
let newObligationDeposits = this.state.deposits;
|
|
454
503
|
let newObligationBorrows = this.state.borrows;
|
|
455
504
|
|
|
505
|
+
// Print deposits and borrows before
|
|
506
|
+
for (const deposit of this.state.deposits) {
|
|
507
|
+
console.log(`Before Deposit: ${deposit.depositReserve.toBase58()} - ${deposit.depositedAmount}`);
|
|
508
|
+
}
|
|
509
|
+
for (const borrow of this.state.borrows) {
|
|
510
|
+
console.log(`Before Borrow: ${borrow.borrowReserve.toBase58()} - ${borrow.borrowedAmountSf}`);
|
|
511
|
+
}
|
|
512
|
+
|
|
456
513
|
switch (action) {
|
|
457
514
|
case 'deposit': {
|
|
458
515
|
if (amountCollateral === undefined || mintCollateral === undefined) {
|
|
@@ -567,6 +624,14 @@ export class KaminoObligation {
|
|
|
567
624
|
null
|
|
568
625
|
);
|
|
569
626
|
|
|
627
|
+
// Print deposits and borrows after
|
|
628
|
+
for (const deposit of newObligationDeposits) {
|
|
629
|
+
console.log(`After Deposit: ${deposit.depositReserve.toBase58()} - ${deposit.depositedAmount}`);
|
|
630
|
+
}
|
|
631
|
+
for (const borrow of newObligationBorrows) {
|
|
632
|
+
console.log(`After Borrow: ${borrow.borrowReserve.toBase58()} - ${borrow.borrowedAmountSf}`);
|
|
633
|
+
}
|
|
634
|
+
|
|
570
635
|
newStats = refreshedStats;
|
|
571
636
|
newDeposits = deposits;
|
|
572
637
|
newBorrows = borrows;
|
|
@@ -921,7 +986,11 @@ export class KaminoObligation {
|
|
|
921
986
|
throw new Error('Reserve not found');
|
|
922
987
|
}
|
|
923
988
|
|
|
924
|
-
const liquidityAvailable = reserve.getLiquidityAvailableForDebtReserveGivenCaps(
|
|
989
|
+
const liquidityAvailable = reserve.getLiquidityAvailableForDebtReserveGivenCaps(
|
|
990
|
+
market,
|
|
991
|
+
[elevationGroup],
|
|
992
|
+
Array.from(this.deposits.keys())
|
|
993
|
+
)[0];
|
|
925
994
|
const maxBorrowAmount = this.getBorrowPower(market, liquidityMint, slot, elevationGroup);
|
|
926
995
|
|
|
927
996
|
if (elevationGroup === this.state.elevationGroup) {
|
|
@@ -1213,7 +1282,8 @@ export class KaminoObligation {
|
|
|
1213
1282
|
public static getRatesForObligation(
|
|
1214
1283
|
kaminoMarket: KaminoMarket,
|
|
1215
1284
|
obligation: Obligation,
|
|
1216
|
-
slot: number
|
|
1285
|
+
slot: number,
|
|
1286
|
+
additionalReserves: PublicKey[] = []
|
|
1217
1287
|
): {
|
|
1218
1288
|
collateralExchangeRates: Map<PublicKey, Decimal>;
|
|
1219
1289
|
cumulativeBorrowRates: Map<PublicKey, Decimal>;
|
|
@@ -1221,12 +1291,14 @@ export class KaminoObligation {
|
|
|
1221
1291
|
const collateralExchangeRates = KaminoObligation.getCollateralExchangeRatesForObligation(
|
|
1222
1292
|
kaminoMarket,
|
|
1223
1293
|
obligation,
|
|
1224
|
-
slot
|
|
1294
|
+
slot,
|
|
1295
|
+
additionalReserves
|
|
1225
1296
|
);
|
|
1226
1297
|
const cumulativeBorrowRates = KaminoObligation.getCumulativeBorrowRatesForObligation(
|
|
1227
1298
|
kaminoMarket,
|
|
1228
1299
|
obligation,
|
|
1229
|
-
slot
|
|
1300
|
+
slot,
|
|
1301
|
+
additionalReserves
|
|
1230
1302
|
);
|
|
1231
1303
|
|
|
1232
1304
|
return {
|
|
@@ -1249,20 +1321,35 @@ export class KaminoObligation {
|
|
|
1249
1321
|
static getCollateralExchangeRatesForObligation(
|
|
1250
1322
|
kaminoMarket: KaminoMarket,
|
|
1251
1323
|
obligation: Obligation,
|
|
1252
|
-
slot: number
|
|
1324
|
+
slot: number,
|
|
1325
|
+
additionalReserves: PublicKey[]
|
|
1253
1326
|
): Map<PublicKey, Decimal> {
|
|
1254
1327
|
const collateralExchangeRates = new PubkeyHashMap<PublicKey, Decimal>();
|
|
1328
|
+
|
|
1329
|
+
// Create a set of all reserves coming from deposit plus additional reserves
|
|
1330
|
+
const allReserves = new Set<PublicKey>();
|
|
1255
1331
|
for (let i = 0; i < obligation.deposits.length; i++) {
|
|
1256
1332
|
const deposit = obligation.deposits[i];
|
|
1257
|
-
if (isNotNullPubkey(deposit.depositReserve)
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1333
|
+
if (isNotNullPubkey(deposit.depositReserve)) {
|
|
1334
|
+
allReserves.add(deposit.depositReserve);
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
for (let i = 0; i < additionalReserves.length; i++) {
|
|
1338
|
+
if (isNotNullPubkey(additionalReserves[i])) {
|
|
1339
|
+
allReserves.add(additionalReserves[i]);
|
|
1264
1340
|
}
|
|
1265
1341
|
}
|
|
1342
|
+
|
|
1343
|
+
// Run through all reserves and get the exchange rate
|
|
1344
|
+
for (const reserve of allReserves) {
|
|
1345
|
+
const reserveInstance = kaminoMarket.getReserveByAddress(reserve)!;
|
|
1346
|
+
const collateralExchangeRate = reserveInstance.getEstimatedCollateralExchangeRate(
|
|
1347
|
+
slot,
|
|
1348
|
+
kaminoMarket.state.referralFeeBps
|
|
1349
|
+
);
|
|
1350
|
+
collateralExchangeRates.set(reserve, collateralExchangeRate);
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1266
1353
|
return collateralExchangeRates;
|
|
1267
1354
|
}
|
|
1268
1355
|
|
|
@@ -1285,16 +1372,39 @@ export class KaminoObligation {
|
|
|
1285
1372
|
}
|
|
1286
1373
|
}
|
|
1287
1374
|
|
|
1288
|
-
static getCumulativeBorrowRatesForObligation(
|
|
1289
|
-
|
|
1375
|
+
static getCumulativeBorrowRatesForObligation(
|
|
1376
|
+
kaminoMarket: KaminoMarket,
|
|
1377
|
+
obligation: Obligation,
|
|
1378
|
+
slot: number,
|
|
1379
|
+
additionalReserves: PublicKey[] = []
|
|
1380
|
+
): Map<PublicKey, Decimal> {
|
|
1381
|
+
const allReserves = new Set<PublicKey>();
|
|
1290
1382
|
for (let i = 0; i < obligation.borrows.length; i++) {
|
|
1291
1383
|
const borrow = obligation.borrows[i];
|
|
1292
|
-
if (isNotNullPubkey(borrow.borrowReserve)
|
|
1293
|
-
|
|
1294
|
-
const cumulativeBorrowRate = reserve.getEstimatedCumulativeBorrowRate(slot, kaminoMarket.state.referralFeeBps);
|
|
1295
|
-
cumulativeBorrowRates.set(reserve.address, cumulativeBorrowRate);
|
|
1384
|
+
if (isNotNullPubkey(borrow.borrowReserve)) {
|
|
1385
|
+
allReserves.add(borrow.borrowReserve);
|
|
1296
1386
|
}
|
|
1297
1387
|
}
|
|
1388
|
+
|
|
1389
|
+
// Add additional reserves
|
|
1390
|
+
for (let i = 0; i < additionalReserves.length; i++) {
|
|
1391
|
+
if (isNotNullPubkey(additionalReserves[i])) {
|
|
1392
|
+
allReserves.add(additionalReserves[i]);
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
const cumulativeBorrowRates = new PubkeyHashMap<PublicKey, Decimal>();
|
|
1397
|
+
|
|
1398
|
+
// Run through all reserves and get the cumulative borrow rate
|
|
1399
|
+
for (const reserve of allReserves) {
|
|
1400
|
+
const reserveInstance = kaminoMarket.getReserveByAddress(reserve)!;
|
|
1401
|
+
const cumulativeBorrowRate = reserveInstance.getEstimatedCumulativeBorrowRate(
|
|
1402
|
+
slot,
|
|
1403
|
+
kaminoMarket.state.referralFeeBps
|
|
1404
|
+
);
|
|
1405
|
+
cumulativeBorrowRates.set(reserve, cumulativeBorrowRate);
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1298
1408
|
return cumulativeBorrowRates;
|
|
1299
1409
|
}
|
|
1300
1410
|
|
package/src/classes/reserve.ts
CHANGED
|
@@ -570,7 +570,7 @@ export class KaminoReserve {
|
|
|
570
570
|
return Decimal.max(new Decimal(0), maxBorrowAmount);
|
|
571
571
|
}
|
|
572
572
|
|
|
573
|
-
|
|
573
|
+
calcSimulatedBorrowRate(
|
|
574
574
|
amount: Decimal,
|
|
575
575
|
action: ActionType,
|
|
576
576
|
slot: number,
|
|
@@ -580,7 +580,20 @@ export class KaminoReserve {
|
|
|
580
580
|
const slotAdjustmentFactor = this.slotAdjustmentFactor();
|
|
581
581
|
const newUtilization = this.calcSimulatedUtilizationRatio(amount, action, slot, referralFeeBps, outflowAmount);
|
|
582
582
|
const curve = truncateBorrowCurve(this.state.config.borrowRateCurve.points);
|
|
583
|
-
return getBorrowRate(newUtilization, curve) * slotAdjustmentFactor
|
|
583
|
+
return getBorrowRate(newUtilization, curve) * slotAdjustmentFactor;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
calcSimulatedBorrowAPR(
|
|
587
|
+
amount: Decimal,
|
|
588
|
+
action: ActionType,
|
|
589
|
+
slot: number,
|
|
590
|
+
referralFeeBps: number,
|
|
591
|
+
outflowAmount?: Decimal
|
|
592
|
+
) {
|
|
593
|
+
return (
|
|
594
|
+
this.calcSimulatedBorrowRate(amount, action, slot, referralFeeBps, outflowAmount) +
|
|
595
|
+
this.getFixedHostInterestRate().toNumber()
|
|
596
|
+
);
|
|
584
597
|
}
|
|
585
598
|
|
|
586
599
|
calcSimulatedSupplyAPR(
|
|
@@ -591,7 +604,7 @@ export class KaminoReserve {
|
|
|
591
604
|
outflowAmount?: Decimal
|
|
592
605
|
) {
|
|
593
606
|
const newUtilization = this.calcSimulatedUtilizationRatio(amount, action, slot, referralFeeBps, outflowAmount);
|
|
594
|
-
const simulatedBorrowAPR = this.
|
|
607
|
+
const simulatedBorrowAPR = this.calcSimulatedBorrowRate(amount, action, slot, referralFeeBps, outflowAmount);
|
|
595
608
|
const protocolTakeRatePct = 1 - this.state.config.protocolTakeRatePct / 100;
|
|
596
609
|
|
|
597
610
|
return newUtilization * simulatedBorrowAPR * protocolTakeRatePct;
|
|
@@ -1033,7 +1046,11 @@ export class KaminoReserve {
|
|
|
1033
1046
|
}
|
|
1034
1047
|
|
|
1035
1048
|
/* This takes into account all the caps */
|
|
1036
|
-
getLiquidityAvailableForDebtReserveGivenCaps(
|
|
1049
|
+
getLiquidityAvailableForDebtReserveGivenCaps(
|
|
1050
|
+
market: KaminoMarket,
|
|
1051
|
+
elevationGroups: number[],
|
|
1052
|
+
collateralReserves: PublicKey[] = []
|
|
1053
|
+
): Decimal[] {
|
|
1037
1054
|
const caps = this.getBorrowCapForReserve(market);
|
|
1038
1055
|
|
|
1039
1056
|
const liquidityAvailable = this.getLiquidityAvailableAmount();
|
|
@@ -1069,7 +1086,16 @@ export class KaminoReserve {
|
|
|
1069
1086
|
(x) => x.elevationGroup === elevationGroup
|
|
1070
1087
|
);
|
|
1071
1088
|
if (capsGivenEgroup.length > 0) {
|
|
1072
|
-
remainingInsideEmodeCaps = Decimal.min(
|
|
1089
|
+
remainingInsideEmodeCaps = Decimal.min(
|
|
1090
|
+
...capsGivenEgroup.map((x) => {
|
|
1091
|
+
// check reserve is part of collReserves array
|
|
1092
|
+
if (collateralReserves.find((collateralReserve) => collateralReserve.equals(x.collateralReserve))) {
|
|
1093
|
+
return x.maxDebt.minus(x.currentValue);
|
|
1094
|
+
} else {
|
|
1095
|
+
return new Decimal(U64_MAX);
|
|
1096
|
+
}
|
|
1097
|
+
})
|
|
1098
|
+
);
|
|
1073
1099
|
}
|
|
1074
1100
|
return Decimal.min(
|
|
1075
1101
|
positiveOrZero(liquidityAvailable),
|
|
@@ -77,7 +77,11 @@ export function calcMaxWithdrawCollateral(
|
|
|
77
77
|
const collPosition = obligation.getDepositByReserve(collReserve.address)!;
|
|
78
78
|
const initialCollValue = collPosition.amount.floor().div(collReserve.getMintFactor()).mul(collOraclePx);
|
|
79
79
|
const remainingDebtAmountLamports = debtPosition.amount.sub(repayAmountLamports);
|
|
80
|
-
const remainingDebtBfWeightedValue = remainingDebtAmountLamports
|
|
80
|
+
const remainingDebtBfWeightedValue = remainingDebtAmountLamports
|
|
81
|
+
.ceil()
|
|
82
|
+
.div(debtReserve.getMintFactor())
|
|
83
|
+
.mul(debtBorrowFactor)
|
|
84
|
+
.mul(debtOraclePx);
|
|
81
85
|
|
|
82
86
|
let isClosingPosition = false;
|
|
83
87
|
if (remainingDebtAmountLamports.lte(new Decimal(0)) && obligation.getBorrows().length === 1) {
|
|
@@ -132,7 +132,11 @@ export async function getRepayWithCollSwapInputs<QuoteResponse>({
|
|
|
132
132
|
const swapQuote = await quoter(swapQuoteInputs, uniqueKlendAccounts);
|
|
133
133
|
|
|
134
134
|
const swapQuotePxDebtToColl = swapQuote.priceAInB;
|
|
135
|
-
const collSwapInLamports = flashRepayAmountLamports
|
|
135
|
+
const collSwapInLamports = flashRepayAmountLamports
|
|
136
|
+
.div(debtReserve.getMintFactor())
|
|
137
|
+
.div(swapQuotePxDebtToColl)
|
|
138
|
+
.mul(collReserve.getMintFactor())
|
|
139
|
+
.ceil();
|
|
136
140
|
|
|
137
141
|
return {
|
|
138
142
|
swapInputs: {
|