@t2000/cli 1.0.1 → 1.1.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/dist/{chunk-G2DXW5RK.js → chunk-KDR2GPAB.js} +85 -92
- package/dist/{chunk-G2DXW5RK.js.map → chunk-KDR2GPAB.js.map} +1 -1
- package/dist/{dist-4CCB73ET.js → dist-67XBQC7P.js} +6 -4
- package/dist/{dist-R6F53QGO.js → dist-SLM2OSSP.js} +54 -98
- package/dist/{dist-R6F53QGO.js.map → dist-SLM2OSSP.js.map} +1 -1
- package/dist/index.js +3 -3
- package/package.json +3 -3
- /package/dist/{dist-4CCB73ET.js.map → dist-67XBQC7P.js.map} +0 -0
|
@@ -60514,18 +60514,22 @@ __export2(cetus_swap_exports, {
|
|
|
60514
60514
|
resolveTokenType: () => resolveTokenType,
|
|
60515
60515
|
simulateSwap: () => simulateSwap
|
|
60516
60516
|
});
|
|
60517
|
-
function getClient(walletAddress) {
|
|
60518
|
-
|
|
60519
|
-
|
|
60517
|
+
function getClient(walletAddress, overlayFee) {
|
|
60518
|
+
const rate = overlayFee?.rate ?? 0;
|
|
60519
|
+
const receiver = overlayFee?.receiver ?? "";
|
|
60520
|
+
const key = `${walletAddress}|${rate}|${receiver}`;
|
|
60521
|
+
const cached = clientCache.get(key);
|
|
60522
|
+
if (cached) return cached;
|
|
60523
|
+
const client = new AggregatorClient({
|
|
60520
60524
|
signer: walletAddress,
|
|
60521
60525
|
env: Env.Mainnet,
|
|
60522
|
-
overlayFeeRate:
|
|
60523
|
-
overlayFeeReceiver: OVERLAY_FEE_RECEIVER
|
|
60526
|
+
...rate > 0 && receiver ? { overlayFeeRate: rate, overlayFeeReceiver: receiver } : {}
|
|
60524
60527
|
});
|
|
60525
|
-
|
|
60528
|
+
clientCache.set(key, client);
|
|
60529
|
+
return client;
|
|
60526
60530
|
}
|
|
60527
60531
|
async function findSwapRoute(params) {
|
|
60528
|
-
const client = getClient(params.walletAddress);
|
|
60532
|
+
const client = getClient(params.walletAddress, params.overlayFee);
|
|
60529
60533
|
const findParams = {
|
|
60530
60534
|
from: params.from,
|
|
60531
60535
|
target: params.to,
|
|
@@ -60562,7 +60566,7 @@ function normalizePriceImpact(value) {
|
|
|
60562
60566
|
return Number.isFinite(n) ? n : 0;
|
|
60563
60567
|
}
|
|
60564
60568
|
async function buildSwapTx(params) {
|
|
60565
|
-
const client = getClient(params.walletAddress);
|
|
60569
|
+
const client = getClient(params.walletAddress, params.overlayFee);
|
|
60566
60570
|
const clampedSlippage = Math.max(1e-3, Math.min(params.slippage, 0.05));
|
|
60567
60571
|
const outputCoin = await client.routerSwap({
|
|
60568
60572
|
router: params.route.routerData,
|
|
@@ -60573,7 +60577,7 @@ async function buildSwapTx(params) {
|
|
|
60573
60577
|
return outputCoin;
|
|
60574
60578
|
}
|
|
60575
60579
|
async function simulateSwap(params) {
|
|
60576
|
-
const client = getClient(params.walletAddress);
|
|
60580
|
+
const client = getClient(params.walletAddress, params.overlayFee);
|
|
60577
60581
|
try {
|
|
60578
60582
|
await client.devInspectTransactionBlock(params.tx);
|
|
60579
60583
|
return { success: true };
|
|
@@ -60582,14 +60586,12 @@ async function simulateSwap(params) {
|
|
|
60582
60586
|
}
|
|
60583
60587
|
}
|
|
60584
60588
|
var OVERLAY_FEE_RATE;
|
|
60585
|
-
var
|
|
60586
|
-
var clientInstance;
|
|
60589
|
+
var clientCache;
|
|
60587
60590
|
var init_cetus_swap = __esm2({
|
|
60588
60591
|
"src/protocols/cetus-swap.ts"() {
|
|
60589
60592
|
init_token_registry();
|
|
60590
60593
|
OVERLAY_FEE_RATE = 1e-3;
|
|
60591
|
-
|
|
60592
|
-
clientInstance = null;
|
|
60594
|
+
clientCache = /* @__PURE__ */ new Map();
|
|
60593
60595
|
}
|
|
60594
60596
|
});
|
|
60595
60597
|
init_errors();
|
|
@@ -60683,13 +60685,13 @@ function assertAllowedAsset(op, asset) {
|
|
|
60683
60685
|
);
|
|
60684
60686
|
}
|
|
60685
60687
|
}
|
|
60686
|
-
|
|
60687
|
-
|
|
60688
|
-
var
|
|
60688
|
+
process.env.T2000_PACKAGE_ID ?? "0xd775fcc66eae26797654d435d751dea56b82eeb999de51fd285348e573b968ad";
|
|
60689
|
+
process.env.T2000_CONFIG_ID ?? "0x08ba26f0d260b5edf6a19c71492b3eb914906a7419baf2df1426765157e5862a";
|
|
60690
|
+
var T2000_OVERLAY_FEE_WALLET = process.env.T2000_OVERLAY_FEE_WALLET ?? "0x5366efbf2b4fe5767fe2e78eb197aa5f5d138d88ac3333fbf3f80a1927da473a";
|
|
60689
60691
|
var DEFAULT_NETWORK = "mainnet";
|
|
60690
60692
|
var DEFAULT_RPC_URL = "https://fullnode.mainnet.sui.io:443";
|
|
60691
60693
|
var DEFAULT_KEY_PATH = "~/.t2000/wallet.key";
|
|
60692
|
-
|
|
60694
|
+
process.env.T2000_API_URL ?? "https://api.t2000.ai";
|
|
60693
60695
|
var CETUS_USDC_SUI_POOL = "0x51e883ba7c0b566a26cbc8a94cd33eb0abd418a77cc1e60ad22fd9b1f29cd2ab";
|
|
60694
60696
|
var GAS_RESERVE_MIN = 0.05;
|
|
60695
60697
|
init_errors();
|
|
@@ -61210,55 +61212,6 @@ function extractCommands(txBlock) {
|
|
|
61210
61212
|
return result;
|
|
61211
61213
|
}
|
|
61212
61214
|
init_token_registry();
|
|
61213
|
-
var FEE_RATES = {
|
|
61214
|
-
save: SAVE_FEE_BPS,
|
|
61215
|
-
borrow: BORROW_FEE_BPS
|
|
61216
|
-
};
|
|
61217
|
-
var OP_CODES = {
|
|
61218
|
-
save: 0,
|
|
61219
|
-
borrow: 2
|
|
61220
|
-
};
|
|
61221
|
-
function calculateFee(operation, amount) {
|
|
61222
|
-
const bps = FEE_RATES[operation];
|
|
61223
|
-
const feeAmount = amount * Number(bps) / Number(BPS_DENOMINATOR);
|
|
61224
|
-
const rawAmount = usdcToRaw(feeAmount);
|
|
61225
|
-
return {
|
|
61226
|
-
amount: feeAmount,
|
|
61227
|
-
asset: "USDC",
|
|
61228
|
-
rate: Number(bps) / Number(BPS_DENOMINATOR),
|
|
61229
|
-
rawAmount
|
|
61230
|
-
};
|
|
61231
|
-
}
|
|
61232
|
-
function addCollectFeeToTx(tx, paymentCoin, operation) {
|
|
61233
|
-
const bps = FEE_RATES[operation];
|
|
61234
|
-
if (bps <= 0n) return;
|
|
61235
|
-
tx.moveCall({
|
|
61236
|
-
target: `${T2000_PACKAGE_ID}::treasury::collect_fee`,
|
|
61237
|
-
typeArguments: [SUPPORTED_ASSETS.USDC.type],
|
|
61238
|
-
arguments: [
|
|
61239
|
-
tx.object(T2000_TREASURY_ID),
|
|
61240
|
-
tx.object(T2000_CONFIG_ID),
|
|
61241
|
-
paymentCoin,
|
|
61242
|
-
tx.pure.u8(OP_CODES[operation])
|
|
61243
|
-
]
|
|
61244
|
-
});
|
|
61245
|
-
}
|
|
61246
|
-
async function reportFee(agentAddress, operation, feeAmount, feeRate, txDigest) {
|
|
61247
|
-
try {
|
|
61248
|
-
await fetch(`${API_BASE_URL}/api/fees`, {
|
|
61249
|
-
method: "POST",
|
|
61250
|
-
headers: { "Content-Type": "application/json" },
|
|
61251
|
-
body: JSON.stringify({
|
|
61252
|
-
agentAddress,
|
|
61253
|
-
operation,
|
|
61254
|
-
feeAmount: feeAmount.toString(),
|
|
61255
|
-
feeRate: feeRate.toString(),
|
|
61256
|
-
txDigest
|
|
61257
|
-
})
|
|
61258
|
-
});
|
|
61259
|
-
} catch {
|
|
61260
|
-
}
|
|
61261
|
-
}
|
|
61262
61215
|
function ulebEncode(num) {
|
|
61263
61216
|
let bigNum = BigInt(num);
|
|
61264
61217
|
const arr = [];
|
|
@@ -65017,9 +64970,6 @@ async function buildSaveTx(client, address, amount, options = {}) {
|
|
|
65017
64970
|
const tx = new Transaction();
|
|
65018
64971
|
tx.setSender(address);
|
|
65019
64972
|
const coinObj = mergeCoins(tx, coins);
|
|
65020
|
-
if (options.collectFee) {
|
|
65021
|
-
addCollectFeeToTx(tx, coinObj, "save");
|
|
65022
|
-
}
|
|
65023
64973
|
const rawAmount = Math.min(Number(stableToRaw(amount, assetInfo.decimals)), Number(totalBalance));
|
|
65024
64974
|
try {
|
|
65025
64975
|
await Ce(tx, assetInfo.type, coinObj, {
|
|
@@ -65090,9 +65040,6 @@ async function addWithdrawToTx(tx, client, address, amount, options = {}) {
|
|
|
65090
65040
|
async function addSaveToTx(tx, _client, _address, coin, options = {}) {
|
|
65091
65041
|
const asset = options.asset ?? "USDC";
|
|
65092
65042
|
const assetInfo = resolveAssetInfo(asset);
|
|
65093
|
-
if (options.collectFee) {
|
|
65094
|
-
addCollectFeeToTx(tx, coin, "save");
|
|
65095
|
-
}
|
|
65096
65043
|
try {
|
|
65097
65044
|
await Ce(tx, assetInfo.type, coin, { env: "prod" });
|
|
65098
65045
|
} catch (err) {
|
|
@@ -65123,9 +65070,6 @@ async function buildBorrowTx(client, address, amount, options = {}) {
|
|
|
65123
65070
|
await refreshOracle(tx, client, address, { skipPythUpdate: options.skipPythUpdate });
|
|
65124
65071
|
try {
|
|
65125
65072
|
const borrowedCoin = await Xe(tx, assetInfo.type, rawAmount, sdkOptions(client));
|
|
65126
|
-
if (options.collectFee) {
|
|
65127
|
-
addCollectFeeToTx(tx, borrowedCoin, "borrow");
|
|
65128
|
-
}
|
|
65129
65073
|
tx.transferObjects([borrowedCoin], address);
|
|
65130
65074
|
} catch (err) {
|
|
65131
65075
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -65133,6 +65077,22 @@ async function buildBorrowTx(client, address, amount, options = {}) {
|
|
|
65133
65077
|
}
|
|
65134
65078
|
return tx;
|
|
65135
65079
|
}
|
|
65080
|
+
async function addBorrowToTx(tx, client, address, amount, options = {}) {
|
|
65081
|
+
if (!amount || amount <= 0 || !Number.isFinite(amount)) {
|
|
65082
|
+
throw new T2000Error("INVALID_AMOUNT", "Borrow amount must be a positive number");
|
|
65083
|
+
}
|
|
65084
|
+
const asset = options.asset ?? "USDC";
|
|
65085
|
+
const assetInfo = resolveAssetInfo(asset);
|
|
65086
|
+
const rawAmount = Number(stableToRaw(amount, assetInfo.decimals));
|
|
65087
|
+
await refreshOracle(tx, client, address, { skipPythUpdate: options.skipPythUpdate });
|
|
65088
|
+
try {
|
|
65089
|
+
const borrowedCoin = await Xe(tx, assetInfo.type, rawAmount, sdkOptions(client));
|
|
65090
|
+
return borrowedCoin;
|
|
65091
|
+
} catch (err) {
|
|
65092
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
65093
|
+
throw new T2000Error("PROTOCOL_UNAVAILABLE", `NAVI borrow failed: ${msg}`);
|
|
65094
|
+
}
|
|
65095
|
+
}
|
|
65136
65096
|
async function buildRepayTx(client, address, amount, options = {}) {
|
|
65137
65097
|
if (!amount || amount <= 0 || !Number.isFinite(amount)) {
|
|
65138
65098
|
throw new T2000Error("INVALID_AMOUNT", "Repay amount must be a positive number");
|
|
@@ -65450,9 +65410,9 @@ var NaviAdapter = class {
|
|
|
65450
65410
|
async getHealth(address) {
|
|
65451
65411
|
return getHealthFactor(this.client, address);
|
|
65452
65412
|
}
|
|
65453
|
-
async buildSaveTx(address, amount, asset
|
|
65413
|
+
async buildSaveTx(address, amount, asset) {
|
|
65454
65414
|
const normalized = normalizeAsset(asset);
|
|
65455
|
-
const tx = await buildSaveTx(this.client, address, amount, {
|
|
65415
|
+
const tx = await buildSaveTx(this.client, address, amount, { asset: normalized });
|
|
65456
65416
|
return { tx };
|
|
65457
65417
|
}
|
|
65458
65418
|
async buildWithdrawTx(address, amount, asset, options) {
|
|
@@ -65490,9 +65450,16 @@ var NaviAdapter = class {
|
|
|
65490
65450
|
skipPythUpdate: options?.skipPythUpdate
|
|
65491
65451
|
});
|
|
65492
65452
|
}
|
|
65493
|
-
async addSaveToTx(tx, address, coin, asset
|
|
65453
|
+
async addSaveToTx(tx, address, coin, asset) {
|
|
65454
|
+
const normalized = normalizeAsset(asset);
|
|
65455
|
+
return addSaveToTx(tx, this.client, address, coin, { asset: normalized });
|
|
65456
|
+
}
|
|
65457
|
+
async addBorrowToTx(tx, address, amount, asset, options) {
|
|
65494
65458
|
const normalized = normalizeAsset(asset);
|
|
65495
|
-
return
|
|
65459
|
+
return addBorrowToTx(tx, this.client, address, amount, {
|
|
65460
|
+
asset: normalized,
|
|
65461
|
+
skipPythUpdate: options?.skipPythUpdate
|
|
65462
|
+
});
|
|
65496
65463
|
}
|
|
65497
65464
|
async addRepayToTx(tx, address, coin, asset, options) {
|
|
65498
65465
|
const normalized = normalizeAsset(asset);
|
|
@@ -66226,7 +66193,6 @@ var T2000 = class _T2000 extends import_index.default {
|
|
|
66226
66193
|
);
|
|
66227
66194
|
}
|
|
66228
66195
|
}
|
|
66229
|
-
const fee = calculateFee("save", amount);
|
|
66230
66196
|
const saveAmount = amount;
|
|
66231
66197
|
const adapter2 = await this.resolveLending(params.protocol, asset, "save");
|
|
66232
66198
|
const canPTB = !!adapter2.addSaveToTx;
|
|
@@ -66239,14 +66205,13 @@ var T2000 = class _T2000 extends import_index.default {
|
|
|
66239
66205
|
const merged = this._mergeCoinsInTx(tx2, coins);
|
|
66240
66206
|
const rawAmount = BigInt(Math.floor(saveAmount * 10 ** assetInfo.decimals));
|
|
66241
66207
|
const [inputCoin] = tx2.splitCoins(merged, [rawAmount]);
|
|
66242
|
-
await adapter2.addSaveToTx(tx2, this._address, inputCoin, asset
|
|
66208
|
+
await adapter2.addSaveToTx(tx2, this._address, inputCoin, asset);
|
|
66243
66209
|
return tx2;
|
|
66244
66210
|
}
|
|
66245
|
-
const { tx } = await adapter2.buildSaveTx(this._address, saveAmount, asset
|
|
66211
|
+
const { tx } = await adapter2.buildSaveTx(this._address, saveAmount, asset);
|
|
66246
66212
|
return tx;
|
|
66247
66213
|
});
|
|
66248
66214
|
const rates = await adapter2.getRates(asset);
|
|
66249
|
-
reportFee(this._address, "save", fee.amount, fee.rate, gasResult.digest);
|
|
66250
66215
|
this.emitBalanceChange(asset, saveAmount, "save", gasResult.digest);
|
|
66251
66216
|
let savingsBalance = saveAmount;
|
|
66252
66217
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
@@ -66266,7 +66231,7 @@ var T2000 = class _T2000 extends import_index.default {
|
|
|
66266
66231
|
tx: gasResult.digest,
|
|
66267
66232
|
amount: saveAmount,
|
|
66268
66233
|
apy: rates.saveApy,
|
|
66269
|
-
fee:
|
|
66234
|
+
fee: 0,
|
|
66270
66235
|
gasCost: gasResult.gasCostSui,
|
|
66271
66236
|
savingsBalance
|
|
66272
66237
|
};
|
|
@@ -66529,21 +66494,19 @@ var T2000 = class _T2000 extends import_index.default {
|
|
|
66529
66494
|
currentHF: maxResult.currentHF
|
|
66530
66495
|
});
|
|
66531
66496
|
}
|
|
66532
|
-
const fee = calculateFee("borrow", params.amount);
|
|
66533
66497
|
const borrowAmount = params.amount;
|
|
66534
66498
|
const gasResult = await executeTx(this.client, this._signer, async () => {
|
|
66535
|
-
const { tx } = await adapter2.buildBorrowTx(this._address, borrowAmount, asset
|
|
66499
|
+
const { tx } = await adapter2.buildBorrowTx(this._address, borrowAmount, asset);
|
|
66536
66500
|
return tx;
|
|
66537
66501
|
});
|
|
66538
66502
|
const hf = await adapter2.getHealth(this._address);
|
|
66539
|
-
reportFee(this._address, "borrow", fee.amount, fee.rate, gasResult.digest);
|
|
66540
66503
|
this.emitBalanceChange(asset, borrowAmount, "borrow", gasResult.digest);
|
|
66541
66504
|
return {
|
|
66542
66505
|
success: true,
|
|
66543
66506
|
tx: gasResult.digest,
|
|
66544
66507
|
amount: borrowAmount,
|
|
66545
66508
|
asset,
|
|
66546
|
-
fee:
|
|
66509
|
+
fee: 0,
|
|
66547
66510
|
healthFactor: hf.healthFactor,
|
|
66548
66511
|
gasCost: gasResult.gasCostSui
|
|
66549
66512
|
};
|
|
@@ -66816,7 +66779,7 @@ var T2000 = class _T2000 extends import_index.default {
|
|
|
66816
66779
|
if (coins.length === 0) throw new T2000Error("INSUFFICIENT_BALANCE", "No USDC coins after swap");
|
|
66817
66780
|
const merged = this._mergeCoinsInTx(tx, coins);
|
|
66818
66781
|
const [inputCoin] = tx.splitCoins(merged, [gainedRaw]);
|
|
66819
|
-
await adapter2.addSaveToTx(tx, this._address, inputCoin, "USDC"
|
|
66782
|
+
await adapter2.addSaveToTx(tx, this._address, inputCoin, "USDC");
|
|
66820
66783
|
return tx;
|
|
66821
66784
|
});
|
|
66822
66785
|
depositTx = depositResult.digest;
|
|
@@ -66941,6 +66904,35 @@ var T2000 = class _T2000 extends import_index.default {
|
|
|
66941
66904
|
}
|
|
66942
66905
|
};
|
|
66943
66906
|
init_errors();
|
|
66907
|
+
var FEE_RATES = {
|
|
66908
|
+
save: SAVE_FEE_BPS,
|
|
66909
|
+
borrow: BORROW_FEE_BPS,
|
|
66910
|
+
// Swap uses Cetus's overlay-fee mechanism (taken from output by the aggregator
|
|
66911
|
+
// and transferred to `overlayFee.receiver`). We list the rate here for display
|
|
66912
|
+
// / quote calculations only — `addFeeTransfer` is NOT called for swaps.
|
|
66913
|
+
swap: 10n
|
|
66914
|
+
// 0.1%
|
|
66915
|
+
};
|
|
66916
|
+
function calculateFee(operation, amount) {
|
|
66917
|
+
const bps = FEE_RATES[operation];
|
|
66918
|
+
const feeAmount = amount * Number(bps) / Number(BPS_DENOMINATOR);
|
|
66919
|
+
const rawAmount = usdcToRaw(feeAmount);
|
|
66920
|
+
return {
|
|
66921
|
+
amount: feeAmount,
|
|
66922
|
+
asset: "USDC",
|
|
66923
|
+
rate: Number(bps) / Number(BPS_DENOMINATOR),
|
|
66924
|
+
rawAmount
|
|
66925
|
+
};
|
|
66926
|
+
}
|
|
66927
|
+
function addFeeTransfer(tx, paymentCoin, feeBps, receiver, amount) {
|
|
66928
|
+
if (feeBps <= 0n) return;
|
|
66929
|
+
if (amount <= 0) return;
|
|
66930
|
+
const feeAmount = amount * Number(feeBps) / Number(BPS_DENOMINATOR);
|
|
66931
|
+
const rawFee = usdcToRaw(feeAmount);
|
|
66932
|
+
if (rawFee <= 0n) return;
|
|
66933
|
+
const [feeCoin] = tx.splitCoins(paymentCoin, [tx.pure.u64(rawFee)]);
|
|
66934
|
+
tx.transferObjects([feeCoin], tx.pure.address(receiver));
|
|
66935
|
+
}
|
|
66944
66936
|
var HF_WARN_THRESHOLD = 1.8;
|
|
66945
66937
|
var HF_CRITICAL_THRESHOLD = 1.3;
|
|
66946
66938
|
var HF_FALLBACK = {
|
|
@@ -67159,6 +67151,7 @@ export {
|
|
|
67159
67151
|
OPERATION_ASSETS,
|
|
67160
67152
|
isAllowedAsset,
|
|
67161
67153
|
assertAllowedAsset,
|
|
67154
|
+
T2000_OVERLAY_FEE_WALLET,
|
|
67162
67155
|
DEFAULT_NETWORK,
|
|
67163
67156
|
CETUS_USDC_SUI_POOL,
|
|
67164
67157
|
GAS_RESERVE_MIN,
|
|
@@ -67197,8 +67190,6 @@ export {
|
|
|
67197
67190
|
parseSuiRpcTx,
|
|
67198
67191
|
extractTxSender,
|
|
67199
67192
|
extractTxCommands,
|
|
67200
|
-
calculateFee,
|
|
67201
|
-
addCollectFeeToTx,
|
|
67202
67193
|
getRates,
|
|
67203
67194
|
getPendingRewards,
|
|
67204
67195
|
ProtocolRegistry,
|
|
@@ -67211,6 +67202,8 @@ export {
|
|
|
67211
67202
|
SafeguardEnforcer,
|
|
67212
67203
|
ContactManager,
|
|
67213
67204
|
T2000,
|
|
67205
|
+
calculateFee,
|
|
67206
|
+
addFeeTransfer,
|
|
67214
67207
|
HF_WARN_THRESHOLD,
|
|
67215
67208
|
HF_CRITICAL_THRESHOLD,
|
|
67216
67209
|
getFinancialSummary,
|
|
@@ -67270,4 +67263,4 @@ axios/dist/node/axios.cjs:
|
|
|
67270
67263
|
@scure/bip39/index.js:
|
|
67271
67264
|
(*! scure-bip39 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
|
|
67272
67265
|
*/
|
|
67273
|
-
//# sourceMappingURL=chunk-
|
|
67266
|
+
//# sourceMappingURL=chunk-KDR2GPAB.js.map
|