@defisaver/positions-sdk 0.0.65 → 0.0.66
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/.yarn/releases/yarn-1.22.1.cjs +147386 -0
- package/.yarn/releases/yarn-1.22.1.js +147386 -0
- package/.yarnrc.yml +1 -0
- package/cjs/aaveV3/index.js +1 -1
- package/cjs/morphoBlue/index.js +1 -1
- package/cjs/staking/staking.d.ts +2 -1
- package/cjs/staking/staking.js +26 -11
- package/esm/aaveV3/index.js +2 -2
- package/esm/morphoBlue/index.js +2 -2
- package/esm/staking/staking.d.ts +2 -1
- package/esm/staking/staking.js +25 -10
- package/package.json +1 -1
- package/src/aaveV3/index.ts +2 -2
- package/src/morphoBlue/index.ts +3 -3
- package/src/staking/staking.ts +21 -6
- package/yarn-error.log +0 -64
package/.yarnrc.yml
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
yarnPath: .yarn/releases/yarn-1.22.1.cjs
|
package/cjs/aaveV3/index.js
CHANGED
|
@@ -175,7 +175,7 @@ function getAaveV3MarketData(web3, network, market, defaultWeb3) {
|
|
|
175
175
|
yield Promise.all(assetsData.map((_market) => __awaiter(this, void 0, void 0, function* () {
|
|
176
176
|
/* eslint-disable no-param-reassign */
|
|
177
177
|
const rewardForMarket = rewardInfo === null || rewardInfo === void 0 ? void 0 : rewardInfo[_market.underlyingTokenAddress];
|
|
178
|
-
if (
|
|
178
|
+
if (staking_1.STAKING_ASSETS.includes(_market.symbol)) {
|
|
179
179
|
_market.incentiveSupplyApy = yield (0, staking_1.getStakingApy)(_market.symbol, defaultWeb3);
|
|
180
180
|
_market.incentiveSupplyToken = _market.symbol;
|
|
181
181
|
}
|
package/cjs/morphoBlue/index.js
CHANGED
|
@@ -102,7 +102,7 @@ function getMorphoBlueMarketData(web3, network, selectedMarket, mainnetWeb3) {
|
|
|
102
102
|
canBeSupplied: true,
|
|
103
103
|
canBeBorrowed: false,
|
|
104
104
|
};
|
|
105
|
-
if (
|
|
105
|
+
if (staking_1.STAKING_ASSETS.includes(collateralTokenInfo.symbol)) {
|
|
106
106
|
assetsData[collateralTokenInfo.symbol].incentiveSupplyApy = yield (0, staking_1.getStakingApy)(collateralTokenInfo.symbol, mainnetWeb3);
|
|
107
107
|
assetsData[collateralTokenInfo.symbol].incentiveSupplyToken = collateralTokenInfo.symbol;
|
|
108
108
|
}
|
package/cjs/staking/staking.d.ts
CHANGED
|
@@ -5,7 +5,8 @@ export declare const getCbETHApr: (web3: Web3, blockNumber?: 'latest' | number)
|
|
|
5
5
|
export declare const getREthApr: (web3: Web3, blockNumber?: 'latest' | number) => Promise<string>;
|
|
6
6
|
export declare const getDsrApy: (web3: Web3, blockNumber?: 'latest' | number) => Promise<string>;
|
|
7
7
|
export declare const getSUSDeApy: () => Promise<any>;
|
|
8
|
-
export declare const
|
|
8
|
+
export declare const STAKING_ASSETS: string[];
|
|
9
|
+
export declare const getStakingApy: (asset: string, web3: Web3, blockNumber?: 'latest' | number, fromBlock?: number | undefined) => Promise<any> | "0" | undefined;
|
|
9
10
|
export declare const calculateInterestEarned: (principal: string, interest: string, type: string, apy?: boolean) => number;
|
|
10
11
|
export declare const calculateNetApy: (usedAssets: MMUsedAssets, assetsData: MMAssetsData, isMorpho?: boolean) => {
|
|
11
12
|
netApy: string;
|
package/cjs/staking/staking.js
CHANGED
|
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.getStETHByWstETHMultiple = exports.getStETHByWstETH = exports.getWstETHByStETH = exports.calculateNetApy = exports.calculateInterestEarned = exports.getStakingApy = exports.getSUSDeApy = exports.getDsrApy = exports.getREthApr = exports.getCbETHApr = exports.getStETHApr = void 0;
|
|
15
|
+
exports.getStETHByWstETHMultiple = exports.getStETHByWstETH = exports.getWstETHByStETH = exports.calculateNetApy = exports.calculateInterestEarned = exports.getStakingApy = exports.STAKING_ASSETS = exports.getSUSDeApy = exports.getDsrApy = exports.getREthApr = exports.getCbETHApr = exports.getStETHApr = void 0;
|
|
16
16
|
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
17
17
|
const contracts_1 = require("../contracts");
|
|
18
18
|
const common_1 = require("../types/common");
|
|
@@ -92,17 +92,32 @@ const getSUSDeApy = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
92
92
|
return data.apy;
|
|
93
93
|
});
|
|
94
94
|
exports.getSUSDeApy = getSUSDeApy;
|
|
95
|
+
const getWeEthApr = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
96
|
+
const res = yield fetch('https://www.etherfi.bid/api/etherfi/apr');
|
|
97
|
+
const data = yield res.json();
|
|
98
|
+
const total = data.latest_aprs.reduce((acc, apr) => new decimal_js_1.default(acc).add(apr).toString());
|
|
99
|
+
return new decimal_js_1.default(total).div(data.latest_aprs.length).div(100).toString();
|
|
100
|
+
});
|
|
101
|
+
exports.STAKING_ASSETS = ['cbETH', 'wstETH', 'cbETH', 'rETH', 'sDAI', 'weETH'];
|
|
95
102
|
const getStakingApy = (asset, web3, blockNumber = 'latest', fromBlock = undefined) => {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
try {
|
|
104
|
+
if (asset === 'stETH' || asset === 'wstETH')
|
|
105
|
+
return (0, exports.getStETHApr)(web3, fromBlock, blockNumber);
|
|
106
|
+
if (asset === 'cbETH')
|
|
107
|
+
return (0, exports.getCbETHApr)(web3, blockNumber);
|
|
108
|
+
if (asset === 'rETH')
|
|
109
|
+
return (0, exports.getREthApr)(web3, blockNumber);
|
|
110
|
+
if (asset === 'sDAI')
|
|
111
|
+
return (0, exports.getDsrApy)(web3);
|
|
112
|
+
if (asset === 'sUSDe')
|
|
113
|
+
return (0, exports.getSUSDeApy)();
|
|
114
|
+
if (asset === 'weETH')
|
|
115
|
+
return getWeEthApr();
|
|
116
|
+
}
|
|
117
|
+
catch (e) {
|
|
118
|
+
console.error(`Failed to fetch APY for ${asset}`);
|
|
119
|
+
return '0';
|
|
120
|
+
}
|
|
106
121
|
};
|
|
107
122
|
exports.getStakingApy = getStakingApy;
|
|
108
123
|
const calculateInterestEarned = (principal, interest, type, apy = false) => {
|
package/esm/aaveV3/index.js
CHANGED
|
@@ -12,7 +12,7 @@ import { assetAmountInEth, assetAmountInWei, getAssetInfo } from '@defisaver/tok
|
|
|
12
12
|
import { AaveIncentiveDataProviderV3Contract, AaveV3ViewContract, createContractWrapper, getConfigContractAbi, getConfigContractAddress, GhoTokenContract, } from '../contracts';
|
|
13
13
|
import { addToObjectIf, ethToWeth, getAbiItem, isLayer2Network, wethToEth, wethToEthByAddress, } from '../services/utils';
|
|
14
14
|
import { NetworkNumber, } from '../types/common';
|
|
15
|
-
import { getStakingApy } from '../staking';
|
|
15
|
+
import { getStakingApy, STAKING_ASSETS } from '../staking';
|
|
16
16
|
import { multicall } from '../multicall';
|
|
17
17
|
import { getAssetsBalances } from '../assets';
|
|
18
18
|
import { calculateBorrowingAssetLimit } from '../moneymarket';
|
|
@@ -166,7 +166,7 @@ export function getAaveV3MarketData(web3, network, market, defaultWeb3) {
|
|
|
166
166
|
yield Promise.all(assetsData.map((_market) => __awaiter(this, void 0, void 0, function* () {
|
|
167
167
|
/* eslint-disable no-param-reassign */
|
|
168
168
|
const rewardForMarket = rewardInfo === null || rewardInfo === void 0 ? void 0 : rewardInfo[_market.underlyingTokenAddress];
|
|
169
|
-
if (
|
|
169
|
+
if (STAKING_ASSETS.includes(_market.symbol)) {
|
|
170
170
|
_market.incentiveSupplyApy = yield getStakingApy(_market.symbol, defaultWeb3);
|
|
171
171
|
_market.incentiveSupplyToken = _market.symbol;
|
|
172
172
|
}
|
package/esm/morphoBlue/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import Dec from 'decimal.js';
|
|
|
11
11
|
import { assetAmountInEth, getAssetInfo, getAssetInfoByAddress } from '@defisaver/tokens';
|
|
12
12
|
import { MorphoBlueViewContract, getConfigContractAbi, getConfigContractAddress, } from '../contracts';
|
|
13
13
|
import { WAD, SECONDS_PER_YEAR, USD_QUOTE } from '../constants';
|
|
14
|
-
import { getStakingApy } from '../staking';
|
|
14
|
+
import { getStakingApy, STAKING_ASSETS } from '../staking';
|
|
15
15
|
import { getAbiItem, wethToEth } from '../services/utils';
|
|
16
16
|
import { multicall } from '../multicall';
|
|
17
17
|
import { getMorphoBlueAggregatedPositionData } from '../helpers/morphoBlueHelpers';
|
|
@@ -96,7 +96,7 @@ export function getMorphoBlueMarketData(web3, network, selectedMarket, mainnetWe
|
|
|
96
96
|
canBeSupplied: true,
|
|
97
97
|
canBeBorrowed: false,
|
|
98
98
|
};
|
|
99
|
-
if (
|
|
99
|
+
if (STAKING_ASSETS.includes(collateralTokenInfo.symbol)) {
|
|
100
100
|
assetsData[collateralTokenInfo.symbol].incentiveSupplyApy = yield getStakingApy(collateralTokenInfo.symbol, mainnetWeb3);
|
|
101
101
|
assetsData[collateralTokenInfo.symbol].incentiveSupplyToken = collateralTokenInfo.symbol;
|
|
102
102
|
}
|
package/esm/staking/staking.d.ts
CHANGED
|
@@ -5,7 +5,8 @@ export declare const getCbETHApr: (web3: Web3, blockNumber?: 'latest' | number)
|
|
|
5
5
|
export declare const getREthApr: (web3: Web3, blockNumber?: 'latest' | number) => Promise<string>;
|
|
6
6
|
export declare const getDsrApy: (web3: Web3, blockNumber?: 'latest' | number) => Promise<string>;
|
|
7
7
|
export declare const getSUSDeApy: () => Promise<any>;
|
|
8
|
-
export declare const
|
|
8
|
+
export declare const STAKING_ASSETS: string[];
|
|
9
|
+
export declare const getStakingApy: (asset: string, web3: Web3, blockNumber?: 'latest' | number, fromBlock?: number | undefined) => Promise<any> | "0" | undefined;
|
|
9
10
|
export declare const calculateInterestEarned: (principal: string, interest: string, type: string, apy?: boolean) => number;
|
|
10
11
|
export declare const calculateNetApy: (usedAssets: MMUsedAssets, assetsData: MMAssetsData, isMorpho?: boolean) => {
|
|
11
12
|
netApy: string;
|
package/esm/staking/staking.js
CHANGED
|
@@ -81,17 +81,32 @@ export const getSUSDeApy = () => __awaiter(void 0, void 0, void 0, function* ()
|
|
|
81
81
|
const data = yield res.json();
|
|
82
82
|
return data.apy;
|
|
83
83
|
});
|
|
84
|
+
const getWeEthApr = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
85
|
+
const res = yield fetch('https://www.etherfi.bid/api/etherfi/apr');
|
|
86
|
+
const data = yield res.json();
|
|
87
|
+
const total = data.latest_aprs.reduce((acc, apr) => new Dec(acc).add(apr).toString());
|
|
88
|
+
return new Dec(total).div(data.latest_aprs.length).div(100).toString();
|
|
89
|
+
});
|
|
90
|
+
export const STAKING_ASSETS = ['cbETH', 'wstETH', 'cbETH', 'rETH', 'sDAI', 'weETH'];
|
|
84
91
|
export const getStakingApy = (asset, web3, blockNumber = 'latest', fromBlock = undefined) => {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
92
|
+
try {
|
|
93
|
+
if (asset === 'stETH' || asset === 'wstETH')
|
|
94
|
+
return getStETHApr(web3, fromBlock, blockNumber);
|
|
95
|
+
if (asset === 'cbETH')
|
|
96
|
+
return getCbETHApr(web3, blockNumber);
|
|
97
|
+
if (asset === 'rETH')
|
|
98
|
+
return getREthApr(web3, blockNumber);
|
|
99
|
+
if (asset === 'sDAI')
|
|
100
|
+
return getDsrApy(web3);
|
|
101
|
+
if (asset === 'sUSDe')
|
|
102
|
+
return getSUSDeApy();
|
|
103
|
+
if (asset === 'weETH')
|
|
104
|
+
return getWeEthApr();
|
|
105
|
+
}
|
|
106
|
+
catch (e) {
|
|
107
|
+
console.error(`Failed to fetch APY for ${asset}`);
|
|
108
|
+
return '0';
|
|
109
|
+
}
|
|
95
110
|
};
|
|
96
111
|
export const calculateInterestEarned = (principal, interest, type, apy = false) => {
|
|
97
112
|
let interval = 1;
|
package/package.json
CHANGED
package/src/aaveV3/index.ts
CHANGED
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
import {
|
|
27
27
|
Blockish, EthAddress, NetworkNumber, PositionBalances,
|
|
28
28
|
} from '../types/common';
|
|
29
|
-
import {
|
|
29
|
+
import {calculateNetApy, getStakingApy, STAKING_ASSETS} from '../staking';
|
|
30
30
|
import { multicall } from '../multicall';
|
|
31
31
|
import { IUiIncentiveDataProviderV3 } from '../types/contracts/generated/AaveUiIncentiveDataProviderV3';
|
|
32
32
|
import { getAssetsBalances } from '../assets';
|
|
@@ -268,7 +268,7 @@ export async function getAaveV3MarketData(web3: Web3, network: NetworkNumber, ma
|
|
|
268
268
|
await Promise.all(assetsData.map(async (_market: AaveV3AssetData) => {
|
|
269
269
|
/* eslint-disable no-param-reassign */
|
|
270
270
|
const rewardForMarket: IUiIncentiveDataProviderV3.AggregatedReserveIncentiveDataStructOutput | undefined = rewardInfo?.[_market.underlyingTokenAddress as any];
|
|
271
|
-
if (
|
|
271
|
+
if (STAKING_ASSETS.includes(_market.symbol)) {
|
|
272
272
|
_market.incentiveSupplyApy = await getStakingApy(_market.symbol, defaultWeb3);
|
|
273
273
|
_market.incentiveSupplyToken = _market.symbol;
|
|
274
274
|
}
|
package/src/morphoBlue/index.ts
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
MorphoBlueAssetsData, MorphoBlueMarketData, MorphoBlueMarketInfo, MorphoBluePositionData,
|
|
11
11
|
} from '../types';
|
|
12
12
|
import { WAD, SECONDS_PER_YEAR, USD_QUOTE } from '../constants';
|
|
13
|
-
import {
|
|
13
|
+
import {getStakingApy, STAKING_ASSETS} from '../staking';
|
|
14
14
|
import { getAbiItem, wethToEth } from '../services/utils';
|
|
15
15
|
import { multicall } from '../multicall';
|
|
16
16
|
import { getMorphoBlueAggregatedPositionData } from '../helpers/morphoBlueHelpers';
|
|
@@ -112,7 +112,7 @@ export async function getMorphoBlueMarketData(web3: Web3, network: NetworkNumber
|
|
|
112
112
|
canBeBorrowed: false,
|
|
113
113
|
};
|
|
114
114
|
|
|
115
|
-
if (
|
|
115
|
+
if (STAKING_ASSETS.includes(collateralTokenInfo.symbol)) {
|
|
116
116
|
assetsData[collateralTokenInfo.symbol].incentiveSupplyApy = await getStakingApy(collateralTokenInfo.symbol, mainnetWeb3);
|
|
117
117
|
assetsData[collateralTokenInfo.symbol].incentiveSupplyToken = collateralTokenInfo.symbol;
|
|
118
118
|
}
|
|
@@ -175,4 +175,4 @@ export async function getMorphoBlueAccountData(web3: Web3, network: NetworkNumbe
|
|
|
175
175
|
usedAssets,
|
|
176
176
|
...getMorphoBlueAggregatedPositionData({ usedAssets, assetsData: marketInfo.assetsData, marketInfo }),
|
|
177
177
|
};
|
|
178
|
-
}
|
|
178
|
+
}
|
package/src/staking/staking.ts
CHANGED
|
@@ -82,12 +82,27 @@ export const getSUSDeApy = async () => {
|
|
|
82
82
|
return data.apy;
|
|
83
83
|
};
|
|
84
84
|
|
|
85
|
+
const getWeEthApr = async () => {
|
|
86
|
+
const res = await fetch('https://www.etherfi.bid/api/etherfi/apr');
|
|
87
|
+
const data = await res.json();
|
|
88
|
+
const total = (data.latest_aprs as string[]).reduce((acc,apr) => new Dec(acc).add(apr).toString());
|
|
89
|
+
return new Dec(total).div(data.latest_aprs.length).div(100).toString();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export const STAKING_ASSETS = ['cbETH', 'wstETH', 'cbETH', 'rETH', 'sDAI','weETH'];
|
|
93
|
+
|
|
85
94
|
export const getStakingApy = (asset: string, web3: Web3, blockNumber: 'latest' | number = 'latest', fromBlock: number | undefined = undefined) => {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
95
|
+
try {
|
|
96
|
+
if (asset === 'stETH' || asset === 'wstETH') return getStETHApr(web3, fromBlock, blockNumber);
|
|
97
|
+
if (asset === 'cbETH') return getCbETHApr(web3, blockNumber);
|
|
98
|
+
if (asset === 'rETH') return getREthApr(web3, blockNumber);
|
|
99
|
+
if (asset === 'sDAI') return getDsrApy(web3);
|
|
100
|
+
if (asset === 'sUSDe') return getSUSDeApy();
|
|
101
|
+
if (asset === 'weETH') return getWeEthApr();
|
|
102
|
+
} catch (e) {
|
|
103
|
+
console.error(`Failed to fetch APY for ${asset}`);
|
|
104
|
+
return '0';
|
|
105
|
+
}
|
|
91
106
|
};
|
|
92
107
|
|
|
93
108
|
export const calculateInterestEarned = (principal: string, interest: string, type: string, apy = false) => {
|
|
@@ -172,4 +187,4 @@ export const getStETHByWstETHMultiple = async (wstEthAmounts: string[] | number[
|
|
|
172
187
|
}));
|
|
173
188
|
const stEthAmounts = await multicall(calls, web3);
|
|
174
189
|
return stEthAmounts.map((arr) => arr[0]);
|
|
175
|
-
};
|
|
190
|
+
};
|
package/yarn-error.log
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
Arguments:
|
|
2
|
-
/Users/stefan/.nvm/versions/node/v14.19.0/bin/node /usr/local/Cellar/yarn/1.22.19/libexec/bin/yarn.js
|
|
3
|
-
|
|
4
|
-
PATH:
|
|
5
|
-
/Users/stefan/.nvm/versions/node/v14.19.0/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/VMware Fusion.app/Contents/Public:/usr/local/go/bin:/Users/stefan/WebstormProjects/defisaver-positions-sdk/node_modules/.bin:/usr/local/go
|
|
6
|
-
|
|
7
|
-
Yarn version:
|
|
8
|
-
1.22.19
|
|
9
|
-
|
|
10
|
-
Node version:
|
|
11
|
-
14.19.0
|
|
12
|
-
|
|
13
|
-
Platform:
|
|
14
|
-
darwin x64
|
|
15
|
-
|
|
16
|
-
Trace:
|
|
17
|
-
Error: incorrect data check
|
|
18
|
-
at Zlib.zlibOnError [as onerror] (zlib.js:187:17)
|
|
19
|
-
|
|
20
|
-
npm manifest:
|
|
21
|
-
{
|
|
22
|
-
"name": "defisaver-positions-sdk",
|
|
23
|
-
"version": "0.0.1",
|
|
24
|
-
"description": "",
|
|
25
|
-
"main": "./cjs/index.js",
|
|
26
|
-
"module": "./esm/src/index.js",
|
|
27
|
-
"types": "./esm/src/index.d.ts",
|
|
28
|
-
"scripts": {
|
|
29
|
-
"build:esm": "rm -rf esm && tsc -p tsconfig.json",
|
|
30
|
-
"build:cjs": "rm -rf cjs && tsc -p tsconfig.cjs.json",
|
|
31
|
-
"build": "npm run build:cjs && npm run build:esm",
|
|
32
|
-
"dev": "tsc -p tsconfig.cjs.json --watch",
|
|
33
|
-
"lint": "eslint src/ --fix",
|
|
34
|
-
"generate-contracts": "node scripts/generateContracts.js",
|
|
35
|
-
"test": "mocha tests/*",
|
|
36
|
-
"build-test": "npm run build && mocha tests/*"
|
|
37
|
-
},
|
|
38
|
-
"keywords": [],
|
|
39
|
-
"author": "",
|
|
40
|
-
"license": "ISC",
|
|
41
|
-
"dependencies": {
|
|
42
|
-
"@defisaver/tokens": "^1.4.56",
|
|
43
|
-
"decimal.js": "^10.4.3"
|
|
44
|
-
},
|
|
45
|
-
"devDependencies": {
|
|
46
|
-
"@defisaver/eslint-config": "^1.0.1",
|
|
47
|
-
"chai": "^4.3.8",
|
|
48
|
-
"dotenv": "^16.3.1",
|
|
49
|
-
"eslint": "^8.49.0",
|
|
50
|
-
"mocha": "^10.2.0",
|
|
51
|
-
"typechain": "^8.3.1",
|
|
52
|
-
"typechain-target-web3-v1-3mihai3": "^6.0.2",
|
|
53
|
-
"typescript": "^5.2.2"
|
|
54
|
-
},
|
|
55
|
-
"peerDependencies": {
|
|
56
|
-
"web3": "^1.10.2"
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
yarn manifest:
|
|
61
|
-
No manifest
|
|
62
|
-
|
|
63
|
-
Lockfile:
|
|
64
|
-
No lockfile
|