@mento-protocol/mento-sdk 0.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/LICENSE +674 -0
- package/README.md +62 -0
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +18 -0
- package/dist/cjs/mento.d.ts +94 -0
- package/dist/cjs/mento.js +222 -0
- package/dist/cjs/utils.d.ts +23 -0
- package/dist/cjs/utils.js +67 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/mento.d.ts +94 -0
- package/dist/esm/mento.js +218 -0
- package/dist/esm/utils.d.ts +23 -0
- package/dist/esm/utils.js +61 -0
- package/package.json +77 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
11
|
+
import { Signer, providers } from 'ethers';
|
|
12
|
+
import { IBroker__factory, IExchangeProvider__factory, } from '@mento-protocol/mento-core-ts';
|
|
13
|
+
import { getBrokerAddressFromRegistry, getSymbolFromTokenAddress, increaseAllowance, } from './utils';
|
|
14
|
+
import { strict as assert } from 'assert';
|
|
15
|
+
export class Mento {
|
|
16
|
+
/**
|
|
17
|
+
* This constructor is private, use the static create or createWithBrokerAddress methods
|
|
18
|
+
* to create a new Mento instance
|
|
19
|
+
* @param brokerAddress the address of the broker contract
|
|
20
|
+
* @param provider an ethers provider
|
|
21
|
+
* @param signer an optional ethers signer to execute swaps (must be connected to a provider)
|
|
22
|
+
*/
|
|
23
|
+
constructor(brokerAddress, signerOrProvider) {
|
|
24
|
+
this.broker = IBroker__factory.connect(brokerAddress, signerOrProvider);
|
|
25
|
+
this.signerOrProvider = signerOrProvider;
|
|
26
|
+
this.exchanges = new Array();
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Creates a new Mento object instance.
|
|
30
|
+
* When constructed with only a Provider only read-only operations are supported
|
|
31
|
+
* @param signerOrProvider an ethers signer or provider. A signer is required to execute swaps
|
|
32
|
+
* @returns a new Mento object instance
|
|
33
|
+
*/
|
|
34
|
+
static create(signerOrProvider) {
|
|
35
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
+
const isSigner = Signer.isSigner(signerOrProvider);
|
|
37
|
+
const isProvider = providers.Provider.isProvider(signerOrProvider);
|
|
38
|
+
if (!isSigner && !isProvider) {
|
|
39
|
+
throw new Error('A valid signer or provider must be provided');
|
|
40
|
+
}
|
|
41
|
+
if (isSigner) {
|
|
42
|
+
if (!providers.Provider.isProvider(signerOrProvider.provider)) {
|
|
43
|
+
throw new Error('Signer must be connected to a provider');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return new Mento(yield getBrokerAddressFromRegistry(signerOrProvider), signerOrProvider);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Create a new Mento object instance given a specific broker address
|
|
51
|
+
* When constructed with only a Provider only read-only operations are supported
|
|
52
|
+
* @param brokerAddr the address of the broker contract
|
|
53
|
+
* @param signerOrProvider an ethers signer or provider. A signer is required to execute swaps
|
|
54
|
+
* @returns a new Mento object instance
|
|
55
|
+
*/
|
|
56
|
+
static createWithBrokerAddress(brokerAddr, signerOrProvider) {
|
|
57
|
+
const isSigner = Signer.isSigner(signerOrProvider);
|
|
58
|
+
const isProvider = providers.Provider.isProvider(signerOrProvider);
|
|
59
|
+
if (!isSigner && !isProvider) {
|
|
60
|
+
throw new Error('A valid signer or provider must be provided');
|
|
61
|
+
}
|
|
62
|
+
if (isSigner) {
|
|
63
|
+
if (!providers.Provider.isProvider(signerOrProvider.provider)) {
|
|
64
|
+
throw new Error('Signer must be connected to a provider');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return new Mento(brokerAddr, signerOrProvider);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Returns a list of all the pairs that can be traded on Mento
|
|
71
|
+
* @returns The list of tradeable pairs in the form of [{address, symbol}]
|
|
72
|
+
*/
|
|
73
|
+
getTradeablePairs() {
|
|
74
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
75
|
+
const exchanges = yield this.getExchanges();
|
|
76
|
+
const pairs = [];
|
|
77
|
+
for (const exchange of exchanges) {
|
|
78
|
+
const asset0 = exchange.assets[0];
|
|
79
|
+
const asset1 = exchange.assets[1];
|
|
80
|
+
const symbols = yield Promise.all([
|
|
81
|
+
getSymbolFromTokenAddress(asset0, this.signerOrProvider),
|
|
82
|
+
getSymbolFromTokenAddress(asset1, this.signerOrProvider),
|
|
83
|
+
]);
|
|
84
|
+
pairs.push([
|
|
85
|
+
{ address: asset0, symbol: symbols[0] },
|
|
86
|
+
{ address: asset1, symbol: symbols[1] },
|
|
87
|
+
]);
|
|
88
|
+
}
|
|
89
|
+
return pairs;
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Returns the amount of tokenIn to be sold to buy amountOut of tokenOut
|
|
94
|
+
* @param tokenIn the token to be sold
|
|
95
|
+
* @param tokenOut the token to be bought
|
|
96
|
+
* @param amountOut the amount of tokenOut to be bought
|
|
97
|
+
* @returns the amount of tokenIn to be sold
|
|
98
|
+
*/
|
|
99
|
+
getAmountIn(tokenIn, tokenOut, amountOut) {
|
|
100
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
101
|
+
const exchange = yield this.getExchangeForTokens(tokenIn, tokenOut);
|
|
102
|
+
return this.broker.getAmountIn(exchange.providerAddr, exchange.id, tokenIn, tokenOut, amountOut);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Returns the amount of tokenOut to be bought by selling amountIn of tokenIn
|
|
107
|
+
* @param tokenIn the token to be sold
|
|
108
|
+
* @param tokenOut the token to be bought
|
|
109
|
+
* @param amountIn the amount of tokenIn to be sold
|
|
110
|
+
* @returns the amount of tokenOut to be bought
|
|
111
|
+
*/
|
|
112
|
+
getAmountOut(tokenIn, tokenOut, amountIn) {
|
|
113
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
114
|
+
const exchange = yield this.getExchangeForTokens(tokenIn, tokenOut);
|
|
115
|
+
return this.broker.getAmountOut(exchange.providerAddr, exchange.id, tokenIn, tokenOut, amountIn);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Increases the broker's trading allowance for the given token
|
|
120
|
+
* @param token the token to increase the allowance for
|
|
121
|
+
* @param amount the amount to increase the allowance by
|
|
122
|
+
* @returns the populated TransactionRequest object
|
|
123
|
+
*/
|
|
124
|
+
increaseTradingAllowance(token, amount) {
|
|
125
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
126
|
+
if (!Signer.isSigner(this.signerOrProvider)) {
|
|
127
|
+
throw new Error('A signer is required to populate the increaseAllowance tx object');
|
|
128
|
+
}
|
|
129
|
+
const spender = this.broker.address;
|
|
130
|
+
const tx = yield increaseAllowance(token, spender, amount, this.signerOrProvider);
|
|
131
|
+
// The contract call doesn't populate all of the signer fields, so we need an extra call for the signer
|
|
132
|
+
return this.signerOrProvider.populateTransaction(tx);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Returns a token swap populated tx object with a fixed amount of tokenIn and a minimum amount of tokenOut
|
|
137
|
+
* Submitting the transaction to execute the swap is left to the consumer
|
|
138
|
+
* @param tokenIn the token to be sold
|
|
139
|
+
* @param tokenOut the token to be bought
|
|
140
|
+
* @param amountIn the amount of tokenIn to be sold
|
|
141
|
+
* @param amountOutMin the minimum amount of tokenOut to be bought
|
|
142
|
+
* @returns the populated TransactionRequest object
|
|
143
|
+
*/
|
|
144
|
+
swapIn(tokenIn, tokenOut, amountIn, amountOutMin) {
|
|
145
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
146
|
+
if (!Signer.isSigner(this.signerOrProvider)) {
|
|
147
|
+
throw new Error('A signer is required to populate the swapIn tx object');
|
|
148
|
+
}
|
|
149
|
+
const exchange = yield this.getExchangeForTokens(tokenIn, tokenOut);
|
|
150
|
+
const tx = yield this.broker.populateTransaction.swapIn(exchange.providerAddr, exchange.id, tokenIn, tokenOut, amountIn, amountOutMin);
|
|
151
|
+
// The broker's call doesn't populate all of the signer fields, so we need an extra call for the signer
|
|
152
|
+
return this.signerOrProvider.populateTransaction(tx);
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Returns a token swap populated tx object with a maximum amount of tokenIn and a fixed amount of tokenOut
|
|
157
|
+
* Submitting the transaction to execute the swap is left to the consumer
|
|
158
|
+
* @param tokenIn the token to be sold
|
|
159
|
+
* @param tokenOut the token to be bought
|
|
160
|
+
* @param amountOut the amount of tokenOut to be bought
|
|
161
|
+
* @param amountInMax the maximum amount of tokenIn to be sold
|
|
162
|
+
* @returns the populated TransactionRequest object
|
|
163
|
+
*/
|
|
164
|
+
swapOut(tokenIn, tokenOut, amountOut, amountInMax) {
|
|
165
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
166
|
+
if (!Signer.isSigner(this.signerOrProvider)) {
|
|
167
|
+
throw new Error('A signer is required to populate the swapOut tx object');
|
|
168
|
+
}
|
|
169
|
+
const exchange = yield this.getExchangeForTokens(tokenIn, tokenOut);
|
|
170
|
+
const tx = yield this.broker.populateTransaction.swapOut(exchange.providerAddr, exchange.id, tokenIn, tokenOut, amountOut, amountInMax);
|
|
171
|
+
// The broker's call doesn't populate all of the signer fields, so we need an extra call for the signer
|
|
172
|
+
return this.signerOrProvider.populateTransaction(tx);
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Returns the list of exchanges available in Mento (cached)
|
|
177
|
+
* @returns the list of exchanges
|
|
178
|
+
*/
|
|
179
|
+
getExchanges() {
|
|
180
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
181
|
+
if (this.exchanges.length > 0) {
|
|
182
|
+
return this.exchanges;
|
|
183
|
+
}
|
|
184
|
+
const exchanges = [];
|
|
185
|
+
const exchangeProvidersAddresses = yield this.broker.getExchangeProviders();
|
|
186
|
+
for (const exchangeProviderAddr of exchangeProvidersAddresses) {
|
|
187
|
+
const exchangeManager = IExchangeProvider__factory.connect(exchangeProviderAddr, this.signerOrProvider);
|
|
188
|
+
const exchangesInManager = yield exchangeManager.getExchanges();
|
|
189
|
+
for (const exchange of exchangesInManager) {
|
|
190
|
+
assert(exchange.assets.length === 2, 'Exchange must have 2 assets');
|
|
191
|
+
exchanges.push({
|
|
192
|
+
providerAddr: exchangeProviderAddr,
|
|
193
|
+
id: exchange.exchangeId,
|
|
194
|
+
assets: exchange.assets,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
this.exchanges = exchanges;
|
|
199
|
+
return exchanges;
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Returns the Mento exchange (if any) for a given pair of tokens
|
|
204
|
+
* @param token0 the first token
|
|
205
|
+
* @param token1 the second token
|
|
206
|
+
* @returns
|
|
207
|
+
*/
|
|
208
|
+
getExchangeForTokens(token0, token1) {
|
|
209
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
210
|
+
const exchanges = (yield this.getExchanges()).filter((e) => e.assets.includes(token0) && e.assets.includes(token1));
|
|
211
|
+
if (exchanges.length === 0) {
|
|
212
|
+
throw Error(`No exchange found for ${token0} and ${token1}`);
|
|
213
|
+
}
|
|
214
|
+
assert(exchanges.length === 1, `More than one exchange found for ${token0} and ${token1}`);
|
|
215
|
+
return exchanges[0];
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { BigNumber, Signer, providers } from 'ethers';
|
|
2
|
+
/**
|
|
3
|
+
* Returns the broker address from the Celo registry
|
|
4
|
+
* @param signerOrProvider an ethers provider or signer
|
|
5
|
+
* @returns the broker address
|
|
6
|
+
*/
|
|
7
|
+
export declare function getBrokerAddressFromRegistry(signerOrProvider: Signer | providers.Provider): Promise<Address>;
|
|
8
|
+
/**
|
|
9
|
+
* Returns the symbol of an erc20 token
|
|
10
|
+
* @param tokenAddr the address of the erc20 token
|
|
11
|
+
* @param signerOrProvider an ethers provider or signer
|
|
12
|
+
* @returns the symbol of the erc20 token
|
|
13
|
+
*/
|
|
14
|
+
export declare function getSymbolFromTokenAddress(tokenAddr: Address, signerOrProvider: Signer | providers.Provider): Promise<string>;
|
|
15
|
+
/**
|
|
16
|
+
* Returns a populated tx obj for increasing the allowance of a spender for a given erc20 token by a given amount
|
|
17
|
+
* @param tokenAddr the address of the erc20 token
|
|
18
|
+
* @param spender the address of the spender
|
|
19
|
+
* @param amount the amount to increase the allowance by
|
|
20
|
+
* @param signer an ethers signer
|
|
21
|
+
* @returns the populated TransactionRequest object
|
|
22
|
+
*/
|
|
23
|
+
export declare function increaseAllowance(tokenAddr: string, spender: string, amount: BigNumber, signer: Signer): Promise<providers.TransactionRequest>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
11
|
+
import { Contract, constants } from 'ethers';
|
|
12
|
+
/**
|
|
13
|
+
* Returns the broker address from the Celo registry
|
|
14
|
+
* @param signerOrProvider an ethers provider or signer
|
|
15
|
+
* @returns the broker address
|
|
16
|
+
*/
|
|
17
|
+
export function getBrokerAddressFromRegistry(signerOrProvider) {
|
|
18
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
const celoRegistryAddress = '0x000000000000000000000000000000000000ce10';
|
|
20
|
+
const brokerIdentifier = 'Broker';
|
|
21
|
+
const registryAbi = [
|
|
22
|
+
'function getAddressForString(string calldata identifier) external view returns (address)',
|
|
23
|
+
];
|
|
24
|
+
const contract = new Contract(celoRegistryAddress, registryAbi, signerOrProvider);
|
|
25
|
+
const brokerAddress = yield contract.getAddressForString(brokerIdentifier);
|
|
26
|
+
if (brokerAddress === constants.AddressZero) {
|
|
27
|
+
throw Error('Broker address not found in the registry');
|
|
28
|
+
}
|
|
29
|
+
return brokerAddress;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Returns the symbol of an erc20 token
|
|
34
|
+
* @param tokenAddr the address of the erc20 token
|
|
35
|
+
* @param signerOrProvider an ethers provider or signer
|
|
36
|
+
* @returns the symbol of the erc20 token
|
|
37
|
+
*/
|
|
38
|
+
export function getSymbolFromTokenAddress(tokenAddr, signerOrProvider) {
|
|
39
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
40
|
+
const erc20Abi = ['function symbol() external view returns (string memory)'];
|
|
41
|
+
const contract = new Contract(tokenAddr, erc20Abi, signerOrProvider);
|
|
42
|
+
return contract.symbol();
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Returns a populated tx obj for increasing the allowance of a spender for a given erc20 token by a given amount
|
|
47
|
+
* @param tokenAddr the address of the erc20 token
|
|
48
|
+
* @param spender the address of the spender
|
|
49
|
+
* @param amount the amount to increase the allowance by
|
|
50
|
+
* @param signer an ethers signer
|
|
51
|
+
* @returns the populated TransactionRequest object
|
|
52
|
+
*/
|
|
53
|
+
export function increaseAllowance(tokenAddr, spender, amount, signer) {
|
|
54
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
55
|
+
const abi = [
|
|
56
|
+
'function increaseAllowance(address spender, uint256 value) external returns (bool)',
|
|
57
|
+
];
|
|
58
|
+
const contract = new Contract(tokenAddr, abi, signer);
|
|
59
|
+
return yield contract.populateTransaction.increaseAllowance(spender, amount);
|
|
60
|
+
});
|
|
61
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mento-protocol/mento-sdk",
|
|
3
|
+
"description": "Official SDK for interacting with the Mento Protocol",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"license": "GPL-3.0-or-later",
|
|
6
|
+
"author": "Mento Labs",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"mento",
|
|
9
|
+
"celo",
|
|
10
|
+
"solidity"
|
|
11
|
+
],
|
|
12
|
+
"main": "dist/cjs/index.js",
|
|
13
|
+
"module": "dist/esm/index.js",
|
|
14
|
+
"typings": "dist/esm/index.d.ts",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"analyze": "size-limit --why",
|
|
20
|
+
"build": "yarn build:cjs && yarn build:esm",
|
|
21
|
+
"build:cjs": "tsc --project ./tsconfig.json",
|
|
22
|
+
"build:esm": "tsc --project ./tsconfig.esm.json",
|
|
23
|
+
"lint": "eslint --config ./.eslintrc.json **/*.{json,ts}",
|
|
24
|
+
"prettier": "prettier --config ./.prettierrc.json --write **/*.{json,md,js,ts,yml}",
|
|
25
|
+
"size": "size-limit",
|
|
26
|
+
"test": "jest --runInBand --verbose",
|
|
27
|
+
"coverage": "jest --coverage"
|
|
28
|
+
},
|
|
29
|
+
"husky": {
|
|
30
|
+
"hooks": {
|
|
31
|
+
"pre-commit": "yarn lint"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"jest": {
|
|
35
|
+
"testEnvironment": "node",
|
|
36
|
+
"testMatch": [
|
|
37
|
+
"**/?(*.)+(test).ts"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=14"
|
|
42
|
+
},
|
|
43
|
+
"size-limit": [
|
|
44
|
+
{
|
|
45
|
+
"path": "dist/sdk.cjs.production.min.js",
|
|
46
|
+
"limit": "10 KB"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"path": "dist/sdk.esm.js",
|
|
50
|
+
"limit": "10 KB"
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@babel/preset-env": "^7.20.2",
|
|
55
|
+
"@babel/preset-typescript": "^7.18.6",
|
|
56
|
+
"@size-limit/preset-small-lib": "^8.1.0",
|
|
57
|
+
"@tsconfig/recommended": "^1.0.1",
|
|
58
|
+
"@types/jest": "^29.4.0",
|
|
59
|
+
"@types/node": "^18.13.0",
|
|
60
|
+
"@typescript-eslint/eslint-plugin": "^5.51.0",
|
|
61
|
+
"@typescript-eslint/parser": "^5.51.0",
|
|
62
|
+
"eslint": "^8.33.0",
|
|
63
|
+
"ethers": "^5.7.2",
|
|
64
|
+
"husky": "^8.0.2",
|
|
65
|
+
"jest": "^29.4.2",
|
|
66
|
+
"prettier": "^2.8.4",
|
|
67
|
+
"size-limit": "^8.1.0",
|
|
68
|
+
"ts-jest": "^29.0.5",
|
|
69
|
+
"typescript": "^4.9.5"
|
|
70
|
+
},
|
|
71
|
+
"dependencies": {
|
|
72
|
+
"@mento-protocol/mento-core-ts": "^0.1.0"
|
|
73
|
+
},
|
|
74
|
+
"peerDependencies": {
|
|
75
|
+
"ethers": "^5.7.2"
|
|
76
|
+
}
|
|
77
|
+
}
|