@scallop-io/sui-scallop-sdk 0.37.3
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 +202 -0
- package/README.md +276 -0
- package/dist/constants/common.d.ts +7 -0
- package/dist/constants/index.d.ts +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1487 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1444 -0
- package/dist/index.mjs.map +1 -0
- package/dist/models/index.d.ts +4 -0
- package/dist/models/scallop.d.ts +46 -0
- package/dist/models/scallopAddress.d.ts +107 -0
- package/dist/models/scallopClient.d.ts +151 -0
- package/dist/models/scallopUtils.d.ts +56 -0
- package/dist/queries/index.d.ts +2 -0
- package/dist/queries/market.d.ts +4 -0
- package/dist/queries/obligation.d.ts +8 -0
- package/dist/txBuilders/coin.d.ts +67 -0
- package/dist/txBuilders/index.d.ts +1 -0
- package/dist/txBuilders/normalMethods.d.ts +3 -0
- package/dist/txBuilders/oracle.d.ts +7 -0
- package/dist/txBuilders/quickMethods.d.ts +7 -0
- package/dist/types/data.d.ts +127 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/model.d.ts +9 -0
- package/dist/types/txBuilder.d.ts +66 -0
- package/package.json +147 -0
- package/src/constants/common.ts +36 -0
- package/src/constants/index.ts +1 -0
- package/src/index.ts +3 -0
- package/src/models/index.ts +4 -0
- package/src/models/scallop.ts +76 -0
- package/src/models/scallopAddress.ts +460 -0
- package/src/models/scallopClient.ts +461 -0
- package/src/models/scallopUtils.ts +133 -0
- package/src/queries/index.ts +2 -0
- package/src/queries/market.ts +16 -0
- package/src/queries/obligation.ts +44 -0
- package/src/txBuilders/coin.ts +38 -0
- package/src/txBuilders/index.ts +1 -0
- package/src/txBuilders/normalMethods.ts +216 -0
- package/src/txBuilders/oracle.ts +376 -0
- package/src/txBuilders/quickMethods.ts +231 -0
- package/src/types/data.ts +170 -0
- package/src/types/index.ts +3 -0
- package/src/types/model.ts +15 -0
- package/src/types/txBuilder.ts +136 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,1444 @@
|
|
|
1
|
+
// src/constants/common.ts
|
|
2
|
+
var API_BASE_URL = "https://sui.api.scallop.io";
|
|
3
|
+
var ADDRESSES_ID = "6462a088a7ace142bb6d7e9b";
|
|
4
|
+
var SUPPORT_ASSET_COINS = [
|
|
5
|
+
"eth",
|
|
6
|
+
"btc",
|
|
7
|
+
"usdc",
|
|
8
|
+
"usdt",
|
|
9
|
+
"sui"
|
|
10
|
+
];
|
|
11
|
+
var SUPPORT_COLLATERAL_COINS = [
|
|
12
|
+
"eth",
|
|
13
|
+
"btc",
|
|
14
|
+
"usdc",
|
|
15
|
+
"usdt",
|
|
16
|
+
"sui"
|
|
17
|
+
];
|
|
18
|
+
var SUPPORT_ORACLES = ["supra", "switchboard", "pyth"];
|
|
19
|
+
var SUPPORT_PACKAGES = [
|
|
20
|
+
"coinDecimalsRegistry",
|
|
21
|
+
"math",
|
|
22
|
+
"whitelist",
|
|
23
|
+
"x",
|
|
24
|
+
"protocol",
|
|
25
|
+
"query",
|
|
26
|
+
"supra",
|
|
27
|
+
"pyth",
|
|
28
|
+
"switchboard",
|
|
29
|
+
"xOracle",
|
|
30
|
+
"testCoin"
|
|
31
|
+
];
|
|
32
|
+
var SUI_COIN_TYPE_ARG_REGEX = /^0x(0*)2::sui::SUI$/;
|
|
33
|
+
|
|
34
|
+
// src/models/scallop.ts
|
|
35
|
+
import { SuiKit as SuiKit5 } from "@scallop-io/sui-kit";
|
|
36
|
+
|
|
37
|
+
// src/models/scallopAddress.ts
|
|
38
|
+
import axios from "axios";
|
|
39
|
+
var ScallopAddress = class {
|
|
40
|
+
constructor(params) {
|
|
41
|
+
const { id, auth, network } = params;
|
|
42
|
+
if (auth)
|
|
43
|
+
this._auth = auth;
|
|
44
|
+
this._id = id;
|
|
45
|
+
this._network = network || "mainnet";
|
|
46
|
+
this._addressesMap = /* @__PURE__ */ new Map();
|
|
47
|
+
this._apiClient = axios.create({
|
|
48
|
+
baseURL: API_BASE_URL,
|
|
49
|
+
headers: {
|
|
50
|
+
"Content-Type": "application/json",
|
|
51
|
+
Accept: "application/json"
|
|
52
|
+
},
|
|
53
|
+
timeout: 3e4
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get addresses API id.
|
|
58
|
+
*
|
|
59
|
+
* @returns The addresses API id.
|
|
60
|
+
*/
|
|
61
|
+
getId() {
|
|
62
|
+
return this._id;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get the address at the provided path.
|
|
66
|
+
*
|
|
67
|
+
* @param path - The path of the address to get.
|
|
68
|
+
* @returns The address at the provided path.
|
|
69
|
+
*/
|
|
70
|
+
get(path) {
|
|
71
|
+
if (this._addresses) {
|
|
72
|
+
const value = path.split(".").reduce(
|
|
73
|
+
(nestedAddressObj, key) => typeof nestedAddressObj === "object" ? nestedAddressObj[key] : nestedAddressObj,
|
|
74
|
+
this._addresses
|
|
75
|
+
);
|
|
76
|
+
return value || void 0;
|
|
77
|
+
} else {
|
|
78
|
+
return void 0;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Set the address at the provided path.
|
|
83
|
+
*
|
|
84
|
+
* @param path - The path of the address to set.
|
|
85
|
+
* @param address - The address be setted to the tartget path.
|
|
86
|
+
* @returns The addresses.
|
|
87
|
+
*/
|
|
88
|
+
set(path, address) {
|
|
89
|
+
if (this._addresses) {
|
|
90
|
+
const keys = path.split(".");
|
|
91
|
+
keys.reduce((nestedAddressObj, key, index) => {
|
|
92
|
+
if (index === keys.length - 1) {
|
|
93
|
+
nestedAddressObj[key] = address;
|
|
94
|
+
} else {
|
|
95
|
+
return nestedAddressObj[key];
|
|
96
|
+
}
|
|
97
|
+
}, this._addresses);
|
|
98
|
+
}
|
|
99
|
+
return this._addresses;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get the addresses.
|
|
103
|
+
*
|
|
104
|
+
* @param network - Specifies which network's addresses you want to get.
|
|
105
|
+
* @returns The addresses.
|
|
106
|
+
*/
|
|
107
|
+
getAddresses(network) {
|
|
108
|
+
if (network) {
|
|
109
|
+
return this._addressesMap.get(network);
|
|
110
|
+
} else {
|
|
111
|
+
return this._addresses;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Set the addresses into addresses map.
|
|
116
|
+
*
|
|
117
|
+
* @param network - Specifies which network's addresses you want to set.
|
|
118
|
+
* @param addresses - The addresses be setted to the tartget network.
|
|
119
|
+
* @returns The addresses.
|
|
120
|
+
*/
|
|
121
|
+
setAddresses(network, addresses) {
|
|
122
|
+
const targetNetwork = network || this._network;
|
|
123
|
+
const targetAddresses = addresses || this._addresses || void 0;
|
|
124
|
+
if (targetAddresses) {
|
|
125
|
+
this._addressesMap.set(targetNetwork, targetAddresses);
|
|
126
|
+
} else {
|
|
127
|
+
this._addressesMap.set(targetNetwork, {
|
|
128
|
+
core: {
|
|
129
|
+
version: "",
|
|
130
|
+
versionCap: "",
|
|
131
|
+
market: "",
|
|
132
|
+
adminCap: "",
|
|
133
|
+
coinDecimalsRegistry: "",
|
|
134
|
+
coins: {
|
|
135
|
+
btc: {
|
|
136
|
+
id: "",
|
|
137
|
+
metaData: "",
|
|
138
|
+
treasury: "",
|
|
139
|
+
oracle: {
|
|
140
|
+
supra: "",
|
|
141
|
+
switchboard: "",
|
|
142
|
+
pyth: {
|
|
143
|
+
feed: "",
|
|
144
|
+
feedObject: ""
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
eth: {
|
|
149
|
+
id: "",
|
|
150
|
+
metaData: "",
|
|
151
|
+
treasury: "",
|
|
152
|
+
oracle: {
|
|
153
|
+
supra: "",
|
|
154
|
+
switchboard: "",
|
|
155
|
+
pyth: {
|
|
156
|
+
feed: "",
|
|
157
|
+
feedObject: ""
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
usdc: {
|
|
162
|
+
id: "",
|
|
163
|
+
metaData: "",
|
|
164
|
+
treasury: "",
|
|
165
|
+
oracle: {
|
|
166
|
+
supra: "",
|
|
167
|
+
switchboard: "",
|
|
168
|
+
pyth: {
|
|
169
|
+
feed: "",
|
|
170
|
+
feedObject: ""
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
usdt: {
|
|
175
|
+
id: "",
|
|
176
|
+
metaData: "",
|
|
177
|
+
treasury: "",
|
|
178
|
+
oracle: {
|
|
179
|
+
supra: "",
|
|
180
|
+
switchboard: "",
|
|
181
|
+
pyth: {
|
|
182
|
+
feed: "",
|
|
183
|
+
feedObject: ""
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
sui: {
|
|
188
|
+
id: "",
|
|
189
|
+
metaData: "",
|
|
190
|
+
treasury: "",
|
|
191
|
+
oracle: {
|
|
192
|
+
supra: "",
|
|
193
|
+
switchboard: "",
|
|
194
|
+
pyth: {
|
|
195
|
+
feed: "",
|
|
196
|
+
feedObject: ""
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
oracles: {
|
|
202
|
+
xOracle: "",
|
|
203
|
+
xOracleCap: "",
|
|
204
|
+
supra: {
|
|
205
|
+
registry: "",
|
|
206
|
+
registryCap: "",
|
|
207
|
+
holder: ""
|
|
208
|
+
},
|
|
209
|
+
switchboard: {
|
|
210
|
+
registry: "",
|
|
211
|
+
registryCap: ""
|
|
212
|
+
},
|
|
213
|
+
pyth: {
|
|
214
|
+
registry: "",
|
|
215
|
+
registryCap: "",
|
|
216
|
+
state: "",
|
|
217
|
+
wormhole: "",
|
|
218
|
+
wormholeState: ""
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
packages: {
|
|
222
|
+
coinDecimalsRegistry: {
|
|
223
|
+
id: "",
|
|
224
|
+
upgradeCap: ""
|
|
225
|
+
},
|
|
226
|
+
math: {
|
|
227
|
+
id: "",
|
|
228
|
+
upgradeCap: ""
|
|
229
|
+
},
|
|
230
|
+
whitelist: {
|
|
231
|
+
id: "",
|
|
232
|
+
upgradeCap: ""
|
|
233
|
+
},
|
|
234
|
+
x: {
|
|
235
|
+
id: "",
|
|
236
|
+
upgradeCap: ""
|
|
237
|
+
},
|
|
238
|
+
protocol: {
|
|
239
|
+
id: "",
|
|
240
|
+
upgradeCap: ""
|
|
241
|
+
},
|
|
242
|
+
query: {
|
|
243
|
+
id: "",
|
|
244
|
+
upgradeCap: ""
|
|
245
|
+
},
|
|
246
|
+
// Deploy by pyth on testnet
|
|
247
|
+
pyth: {
|
|
248
|
+
id: "",
|
|
249
|
+
upgradeCap: ""
|
|
250
|
+
},
|
|
251
|
+
// Deploy by ourself on testnet
|
|
252
|
+
switchboard: {
|
|
253
|
+
id: "",
|
|
254
|
+
upgradeCap: ""
|
|
255
|
+
},
|
|
256
|
+
xOracle: {
|
|
257
|
+
id: "",
|
|
258
|
+
upgradeCap: ""
|
|
259
|
+
},
|
|
260
|
+
// Deploy for faucet on testnet
|
|
261
|
+
testCoin: {
|
|
262
|
+
id: "",
|
|
263
|
+
upgradeCap: ""
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Get all addresses.
|
|
272
|
+
*
|
|
273
|
+
* @returns All addresses.
|
|
274
|
+
*/
|
|
275
|
+
getAllAddresses() {
|
|
276
|
+
return Object.fromEntries(this._addressesMap);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Create a new address through the API and synchronize it back to the
|
|
280
|
+
* instance. If the `network` is not specified, the mainnet is used by default.
|
|
281
|
+
* If no `addresses` is provided, an addresses with all empty strings is created
|
|
282
|
+
* by default.
|
|
283
|
+
*
|
|
284
|
+
* This function only allows for one addresses to be input into a specific network
|
|
285
|
+
* at a time, and does not provide an addresses map for setting addresses
|
|
286
|
+
* across all networks at once.
|
|
287
|
+
*
|
|
288
|
+
* @param network - Specifies which network's addresses you want to set.
|
|
289
|
+
* @param addresses - The addresses be setted to the tartget network.
|
|
290
|
+
* @param auth - The authentication API key.
|
|
291
|
+
* @returns The addresses.
|
|
292
|
+
*/
|
|
293
|
+
async create(network, addresses, auth) {
|
|
294
|
+
const apiKey = auth || this._auth || void 0;
|
|
295
|
+
const targetNetwork = network || this._network;
|
|
296
|
+
const targetAddresses = addresses || this._addresses || void 0;
|
|
297
|
+
if (apiKey !== void 0) {
|
|
298
|
+
this._addressesMap.clear();
|
|
299
|
+
this.setAddresses(targetNetwork, targetAddresses);
|
|
300
|
+
const response = await this._apiClient.post(
|
|
301
|
+
`${API_BASE_URL}/addresses`,
|
|
302
|
+
JSON.stringify(Object.fromEntries(this._addressesMap)),
|
|
303
|
+
{
|
|
304
|
+
headers: {
|
|
305
|
+
"Content-Type": "application/json",
|
|
306
|
+
"api-key": auth || this._auth
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
);
|
|
310
|
+
if (response.status === 201) {
|
|
311
|
+
for (const [network2, addresses2] of Object.entries(
|
|
312
|
+
response.data
|
|
313
|
+
)) {
|
|
314
|
+
if (["localnet", "devnet", "testnet", "mainnet"].includes(network2)) {
|
|
315
|
+
if (network2 === this._network)
|
|
316
|
+
this._addresses = addresses2;
|
|
317
|
+
this._addressesMap.set(network2, addresses2);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
this._id = response.data.id;
|
|
321
|
+
return this._addresses;
|
|
322
|
+
} else {
|
|
323
|
+
throw Error("Failed to create addresses.");
|
|
324
|
+
}
|
|
325
|
+
} else {
|
|
326
|
+
throw Error("You don't have permission to access this request.");
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* It doesn't read the data stored in the address instance, but reads and
|
|
331
|
+
* synchronizes the data from the API into instance.
|
|
332
|
+
*
|
|
333
|
+
* @param id - The id of the addresses to get.
|
|
334
|
+
* @returns The addresses.
|
|
335
|
+
*/
|
|
336
|
+
async read(id) {
|
|
337
|
+
const addressesId = id || this._id || void 0;
|
|
338
|
+
if (addressesId !== void 0) {
|
|
339
|
+
const response = await this._apiClient.get(
|
|
340
|
+
`${API_BASE_URL}/addresses/${addressesId}`,
|
|
341
|
+
{
|
|
342
|
+
headers: {
|
|
343
|
+
"Content-Type": "application/json"
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
);
|
|
347
|
+
if (response.status === 200) {
|
|
348
|
+
for (const [network, addresses] of Object.entries(
|
|
349
|
+
response.data
|
|
350
|
+
)) {
|
|
351
|
+
if (["localnet", "devnet", "testnet", "mainnet"].includes(network)) {
|
|
352
|
+
if (network === this._network)
|
|
353
|
+
this._addresses = addresses;
|
|
354
|
+
this._addressesMap.set(network, addresses);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
this._id = response.data.id;
|
|
358
|
+
return this._addresses;
|
|
359
|
+
} else {
|
|
360
|
+
throw Error("Failed to create addresses.");
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Update the address through the API and synchronize it back to the
|
|
366
|
+
* instance. If the `network` is not specified, the mainnet is used by default.
|
|
367
|
+
* If no `addresses` is provided, an addresses with all empty strings is created
|
|
368
|
+
* by default.
|
|
369
|
+
*
|
|
370
|
+
* This function only allows for one addresses to be input into a specific network
|
|
371
|
+
* at a time, and does not provide an addresses map for setting addresses
|
|
372
|
+
* across all networks at once.
|
|
373
|
+
*
|
|
374
|
+
* @param id - The id of the addresses to update.
|
|
375
|
+
* @param network - Specifies which network's addresses you want to set.
|
|
376
|
+
* @param addresses - The addresses be setted to the tartget network.
|
|
377
|
+
* @param auth - The authentication api key.
|
|
378
|
+
* @returns The addresses.
|
|
379
|
+
*/
|
|
380
|
+
async update(id, network, addresses, auth) {
|
|
381
|
+
const apiKey = auth || this._auth || void 0;
|
|
382
|
+
const targetId = id || this._id || void 0;
|
|
383
|
+
const targetNetwork = network || this._network;
|
|
384
|
+
const targetAddresses = addresses || this._addresses || void 0;
|
|
385
|
+
if (targetId === void 0)
|
|
386
|
+
throw Error("Require addresses id.");
|
|
387
|
+
if (apiKey !== void 0) {
|
|
388
|
+
if (id !== this._id) {
|
|
389
|
+
this._addressesMap.clear();
|
|
390
|
+
}
|
|
391
|
+
this.setAddresses(targetNetwork, targetAddresses);
|
|
392
|
+
const response = await this._apiClient.put(
|
|
393
|
+
`${API_BASE_URL}/addresses/${targetId}`,
|
|
394
|
+
JSON.stringify(Object.fromEntries(this._addressesMap)),
|
|
395
|
+
{
|
|
396
|
+
headers: {
|
|
397
|
+
"Content-Type": "application/json",
|
|
398
|
+
"api-key": auth || this._auth
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
);
|
|
402
|
+
if (response.status === 200) {
|
|
403
|
+
for (const [network2, addresses2] of Object.entries(
|
|
404
|
+
response.data
|
|
405
|
+
)) {
|
|
406
|
+
if (["localnet", "devnet", "testnet", "mainnet"].includes(network2)) {
|
|
407
|
+
if (network2 === this._network)
|
|
408
|
+
this._addresses = addresses2;
|
|
409
|
+
this._addressesMap.set(network2, addresses2);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
this._id = response.data.id;
|
|
413
|
+
return this._addresses;
|
|
414
|
+
} else {
|
|
415
|
+
throw Error("Failed to update addresses.");
|
|
416
|
+
}
|
|
417
|
+
} else {
|
|
418
|
+
throw Error("You don't have permission to access this request.");
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Deletes all addresses of a specified id through the API and synchronizes
|
|
423
|
+
* them back to the instance.
|
|
424
|
+
*
|
|
425
|
+
* @param id - The id of the addresses to delete.
|
|
426
|
+
* @param auth - The authentication API key.
|
|
427
|
+
*/
|
|
428
|
+
async delete(id, auth) {
|
|
429
|
+
const apiKey = auth || this._auth || void 0;
|
|
430
|
+
const targetId = id || this._id || void 0;
|
|
431
|
+
if (targetId === void 0)
|
|
432
|
+
throw Error("Require addresses id.");
|
|
433
|
+
if (apiKey !== void 0) {
|
|
434
|
+
const response = await this._apiClient.delete(
|
|
435
|
+
`${API_BASE_URL}/addresses/${targetId}`,
|
|
436
|
+
{
|
|
437
|
+
headers: {
|
|
438
|
+
"Content-Type": "application/json",
|
|
439
|
+
"api-key": auth || this._auth
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
);
|
|
443
|
+
if (response.status === 200) {
|
|
444
|
+
this._id = void 0;
|
|
445
|
+
this._addresses = void 0;
|
|
446
|
+
this._addressesMap.clear();
|
|
447
|
+
} else {
|
|
448
|
+
throw Error("Failed to delete addresses.");
|
|
449
|
+
}
|
|
450
|
+
} else {
|
|
451
|
+
throw Error("You don't have permission to access this request.");
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
// src/models/scallopClient.ts
|
|
457
|
+
import { normalizeSuiAddress } from "@mysten/sui.js";
|
|
458
|
+
import { SuiKit as SuiKit4 } from "@scallop-io/sui-kit";
|
|
459
|
+
|
|
460
|
+
// src/models/scallopUtils.ts
|
|
461
|
+
import {
|
|
462
|
+
SUI_FRAMEWORK_ADDRESS,
|
|
463
|
+
SUI_TYPE_ARG,
|
|
464
|
+
normalizeStructTag
|
|
465
|
+
} from "@mysten/sui.js";
|
|
466
|
+
import { SuiKit } from "@scallop-io/sui-kit";
|
|
467
|
+
import { PriceServiceConnection } from "@pythnetwork/price-service-client";
|
|
468
|
+
var ScallopUtils = class {
|
|
469
|
+
constructor(params) {
|
|
470
|
+
this._suiKit = new SuiKit(params);
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* @description Select coin id that add up to the given amount as transaction arguments.
|
|
474
|
+
* @param owner The address of the owner.
|
|
475
|
+
* @param amount The amount that is needed for the coin.
|
|
476
|
+
* @param coinType The coin type, default is 0x2::SUI::SUI.
|
|
477
|
+
* @return The selected transaction coin arguments.
|
|
478
|
+
*/
|
|
479
|
+
async selectCoins(owner, amount, coinType = SUI_TYPE_ARG) {
|
|
480
|
+
const coins = await this._suiKit.rpcProvider.selectCoins(
|
|
481
|
+
owner,
|
|
482
|
+
amount,
|
|
483
|
+
coinType
|
|
484
|
+
);
|
|
485
|
+
return coins.map((c) => c.objectId);
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* @description Fetch price feed VAAs of interest from the Pyth.
|
|
489
|
+
* @param priceIds Array of hex-encoded price ids.
|
|
490
|
+
* @param isTestnet Specify whether it is a test network.
|
|
491
|
+
* @return Array of base64 encoded VAAs.
|
|
492
|
+
*/
|
|
493
|
+
async getVaas(priceIds, isTestnet) {
|
|
494
|
+
const connection = new PriceServiceConnection(
|
|
495
|
+
isTestnet ? "https://xc-testnet.pyth.network" : "https://xc-mainnet.pyth.network",
|
|
496
|
+
{
|
|
497
|
+
priceFeedRequestConfig: {
|
|
498
|
+
binary: true
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
);
|
|
502
|
+
return await connection.getLatestVaas(priceIds);
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* @description Handle non-standard coins.
|
|
506
|
+
* @param coinPackageId Package id of coin.
|
|
507
|
+
* @param coinName specific support coin name.
|
|
508
|
+
* @return coinType.
|
|
509
|
+
*/
|
|
510
|
+
parseCoinType(coinPackageId, coinName) {
|
|
511
|
+
if (coinName === "sui")
|
|
512
|
+
return normalizeStructTag(SUI_TYPE_ARG);
|
|
513
|
+
const wormHoleCoins = [
|
|
514
|
+
// USDC
|
|
515
|
+
"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf",
|
|
516
|
+
// USDT
|
|
517
|
+
"0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c"
|
|
518
|
+
];
|
|
519
|
+
if (wormHoleCoins.includes(coinPackageId)) {
|
|
520
|
+
return `${coinPackageId}::coin::COIN`;
|
|
521
|
+
} else {
|
|
522
|
+
return `${coinPackageId}::${coinName}::${coinName.toUpperCase()}`;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* @description Handle non-standard coin names.
|
|
527
|
+
* @param coinPackageId Package id of coin.
|
|
528
|
+
* @param coinName specific support coin name.
|
|
529
|
+
* @return coinType.
|
|
530
|
+
*/
|
|
531
|
+
getCoinNameFromCoinType(coinType) {
|
|
532
|
+
const wormHoleCoinTypes = [
|
|
533
|
+
// USDC
|
|
534
|
+
"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN",
|
|
535
|
+
// USDT
|
|
536
|
+
"0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN"
|
|
537
|
+
];
|
|
538
|
+
if (coinType === wormHoleCoinTypes[0]) {
|
|
539
|
+
return "usdc";
|
|
540
|
+
} else if (coinType === wormHoleCoinTypes[1]) {
|
|
541
|
+
return "usdt";
|
|
542
|
+
} else {
|
|
543
|
+
return coinType.split("::")[2].toLowerCase();
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* @description Handle market coin types.
|
|
548
|
+
*
|
|
549
|
+
* @param coinPackageId Package id of coin.
|
|
550
|
+
* @param protocolPkgId Package id of protocol.
|
|
551
|
+
* @param coinName specific support coin name.
|
|
552
|
+
*
|
|
553
|
+
* @return marketCoinType.
|
|
554
|
+
*/
|
|
555
|
+
parseMarketCoinType(coinPackageId, protocolPkgId, coinName) {
|
|
556
|
+
const coinType = this.parseCoinType(
|
|
557
|
+
coinName === "sui" ? SUI_FRAMEWORK_ADDRESS : coinPackageId,
|
|
558
|
+
coinName
|
|
559
|
+
);
|
|
560
|
+
return `${protocolPkgId}::reserve::MarketCoin<${coinType}>`;
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
// src/queries/market.ts
|
|
565
|
+
import { SuiTxBlock } from "@scallop-io/sui-kit";
|
|
566
|
+
var queryMarket = async (scallopAddress, suiKit) => {
|
|
567
|
+
const packageId = scallopAddress.get("core.packages.query.id");
|
|
568
|
+
const marketId = scallopAddress.get("core.market");
|
|
569
|
+
const txBlock = new SuiTxBlock();
|
|
570
|
+
const queryTarget = `${packageId}::market_query::market_data`;
|
|
571
|
+
txBlock.moveCall(queryTarget, [marketId]);
|
|
572
|
+
const queryResult = await suiKit.inspectTxn(txBlock);
|
|
573
|
+
return queryResult.events[0].parsedJson;
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
// src/queries/obligation.ts
|
|
577
|
+
import { SuiTxBlock as SuiTxBlock2 } from "@scallop-io/sui-kit";
|
|
578
|
+
var queryObligation = async (obligationId, scallopAddress, suiKit) => {
|
|
579
|
+
const packageId = scallopAddress.get("core.packages.query.id");
|
|
580
|
+
const queryTarget = `${packageId}::obligation_query::obligation_data`;
|
|
581
|
+
const txBlock = new SuiTxBlock2();
|
|
582
|
+
txBlock.moveCall(queryTarget, [obligationId]);
|
|
583
|
+
const queryResult = await suiKit.inspectTxn(txBlock);
|
|
584
|
+
return queryResult.events[0].parsedJson;
|
|
585
|
+
};
|
|
586
|
+
var getObligations = async (ownerAddress, scallopAddress, suiKit) => {
|
|
587
|
+
const owner = ownerAddress || suiKit.currentAddress();
|
|
588
|
+
const keyObjectRefs = await suiKit.provider().getOwnedObjects({
|
|
589
|
+
owner,
|
|
590
|
+
filter: {
|
|
591
|
+
StructType: `${scallopAddress.get(
|
|
592
|
+
"core.packages.protocol.id"
|
|
593
|
+
)}::obligation::ObligationKey`
|
|
594
|
+
}
|
|
595
|
+
});
|
|
596
|
+
const keyIds = keyObjectRefs.data.map((ref) => ref?.data?.objectId).filter((id) => id !== void 0);
|
|
597
|
+
const keyObjects = await suiKit.getObjects(keyIds);
|
|
598
|
+
const obligations = [];
|
|
599
|
+
for (const keyObject of keyObjects) {
|
|
600
|
+
const keyId = keyObject.objectId;
|
|
601
|
+
const fields = keyObject.objectFields;
|
|
602
|
+
const obligationId = fields["ownership"]["fields"]["of"];
|
|
603
|
+
obligations.push({ id: obligationId, keyId });
|
|
604
|
+
}
|
|
605
|
+
return obligations;
|
|
606
|
+
};
|
|
607
|
+
|
|
608
|
+
// src/txBuilders/normalMethods.ts
|
|
609
|
+
import { SUI_CLOCK_OBJECT_ID } from "@mysten/sui.js";
|
|
610
|
+
import { SuiTxBlock as SuiTxBlock3 } from "@scallop-io/sui-kit";
|
|
611
|
+
var scallopNormalMethodsHandler = {
|
|
612
|
+
openObligation: ({ txBlock, coreIds }) => () => txBlock.moveCall(
|
|
613
|
+
`${coreIds.protocolPkg}::open_obligation::open_obligation`,
|
|
614
|
+
[coreIds.version]
|
|
615
|
+
),
|
|
616
|
+
returnObligation: ({ txBlock, coreIds }) => (obligation, obligationHotPotato) => txBlock.moveCall(
|
|
617
|
+
`${coreIds.protocolPkg}::open_obligation::return_obligation`,
|
|
618
|
+
[coreIds.version, obligation, obligationHotPotato]
|
|
619
|
+
),
|
|
620
|
+
openObligationEntry: ({ txBlock, coreIds }) => () => txBlock.moveCall(
|
|
621
|
+
`${coreIds.protocolPkg}::open_obligation::open_obligation_entry`,
|
|
622
|
+
[coreIds.version]
|
|
623
|
+
),
|
|
624
|
+
addCollateral: ({ txBlock, coreIds, scallopUtils, scallopAddress }) => (obligation, coin, coinName) => {
|
|
625
|
+
const coinPackageId = scallopAddress.get(`core.coins.${coinName}.id`);
|
|
626
|
+
const coinType = scallopUtils.parseCoinType(coinPackageId, coinName);
|
|
627
|
+
return txBlock.moveCall(
|
|
628
|
+
`${coreIds.protocolPkg}::deposit_collateral::deposit_collateral`,
|
|
629
|
+
[coreIds.version, obligation, coreIds.market, coin],
|
|
630
|
+
[coinType]
|
|
631
|
+
);
|
|
632
|
+
},
|
|
633
|
+
takeCollateral: ({ txBlock, coreIds, scallopAddress, scallopUtils }) => (obligation, obligationKey, amount, coinName) => {
|
|
634
|
+
const coinPackageId = scallopAddress.get(`core.coins.${coinName}.id`);
|
|
635
|
+
const coinType = scallopUtils.parseCoinType(coinPackageId, coinName);
|
|
636
|
+
return txBlock.moveCall(
|
|
637
|
+
`${coreIds.protocolPkg}::withdraw_collateral::withdraw_collateral`,
|
|
638
|
+
[
|
|
639
|
+
coreIds.version,
|
|
640
|
+
obligation,
|
|
641
|
+
obligationKey,
|
|
642
|
+
coreIds.market,
|
|
643
|
+
coreIds.dmlR,
|
|
644
|
+
amount,
|
|
645
|
+
coreIds.oracle,
|
|
646
|
+
SUI_CLOCK_OBJECT_ID
|
|
647
|
+
],
|
|
648
|
+
[coinType]
|
|
649
|
+
);
|
|
650
|
+
},
|
|
651
|
+
deposit: ({ txBlock, coreIds, scallopAddress, scallopUtils }) => (coin, coinName) => {
|
|
652
|
+
const coinPackageId = scallopAddress.get(`core.coins.${coinName}.id`);
|
|
653
|
+
const coinType = scallopUtils.parseCoinType(coinPackageId, coinName);
|
|
654
|
+
return txBlock.moveCall(
|
|
655
|
+
`${coreIds.protocolPkg}::mint::mint`,
|
|
656
|
+
[coreIds.version, coreIds.market, coin, SUI_CLOCK_OBJECT_ID],
|
|
657
|
+
[coinType]
|
|
658
|
+
);
|
|
659
|
+
},
|
|
660
|
+
depositEntry: ({ txBlock, coreIds, scallopAddress, scallopUtils }) => (coin, coinName) => {
|
|
661
|
+
const coinPackageId = scallopAddress.get(`core.coins.${coinName}.id`);
|
|
662
|
+
const coinType = scallopUtils.parseCoinType(coinPackageId, coinName);
|
|
663
|
+
return txBlock.moveCall(
|
|
664
|
+
`${coreIds.protocolPkg}::mint::mint_entry`,
|
|
665
|
+
[coreIds.version, coreIds.market, coin, SUI_CLOCK_OBJECT_ID],
|
|
666
|
+
[coinType]
|
|
667
|
+
);
|
|
668
|
+
},
|
|
669
|
+
withdraw: ({ txBlock, coreIds, scallopAddress, scallopUtils }) => (marketCoin, coinName) => {
|
|
670
|
+
const coinPackageId = scallopAddress.get(`core.coins.${coinName}.id`);
|
|
671
|
+
const coinType = scallopUtils.parseCoinType(coinPackageId, coinName);
|
|
672
|
+
return txBlock.moveCall(
|
|
673
|
+
`${coreIds.protocolPkg}::redeem::redeem`,
|
|
674
|
+
[coreIds.version, coreIds.market, marketCoin, SUI_CLOCK_OBJECT_ID],
|
|
675
|
+
[coinType]
|
|
676
|
+
);
|
|
677
|
+
},
|
|
678
|
+
withdrawEntry: ({ txBlock, coreIds, scallopAddress, scallopUtils }) => (marketCoin, coinName) => {
|
|
679
|
+
const coinPackageId = scallopAddress.get(`core.coins.${coinName}.id`);
|
|
680
|
+
const coinType = scallopUtils.parseCoinType(coinPackageId, coinName);
|
|
681
|
+
return txBlock.moveCall(
|
|
682
|
+
`${coreIds.protocolPkg}::redeem::redeem_entry`,
|
|
683
|
+
[coreIds.version, coreIds.market, marketCoin, SUI_CLOCK_OBJECT_ID],
|
|
684
|
+
[coinType]
|
|
685
|
+
);
|
|
686
|
+
},
|
|
687
|
+
borrow: ({ txBlock, coreIds, scallopAddress, scallopUtils }) => (obligation, obligationKey, amount, coinName) => {
|
|
688
|
+
const coinPackageId = scallopAddress.get(`core.coins.${coinName}.id`);
|
|
689
|
+
const coinType = scallopUtils.parseCoinType(coinPackageId, coinName);
|
|
690
|
+
return txBlock.moveCall(
|
|
691
|
+
`${coreIds.protocolPkg}::borrow::borrow`,
|
|
692
|
+
[
|
|
693
|
+
coreIds.version,
|
|
694
|
+
obligation,
|
|
695
|
+
obligationKey,
|
|
696
|
+
coreIds.market,
|
|
697
|
+
coreIds.dmlR,
|
|
698
|
+
amount,
|
|
699
|
+
coreIds.oracle,
|
|
700
|
+
SUI_CLOCK_OBJECT_ID
|
|
701
|
+
],
|
|
702
|
+
[coinType]
|
|
703
|
+
);
|
|
704
|
+
},
|
|
705
|
+
borrowEntry: ({ txBlock, coreIds, scallopAddress, scallopUtils }) => (obligation, obligationKey, amount, coinName) => {
|
|
706
|
+
const coinPackageId = scallopAddress.get(`core.coins.${coinName}.id`);
|
|
707
|
+
const coinType = scallopUtils.parseCoinType(coinPackageId, coinName);
|
|
708
|
+
return txBlock.moveCall(
|
|
709
|
+
`${coreIds.protocolPkg}::borrow::borrow_entry`,
|
|
710
|
+
[
|
|
711
|
+
coreIds.version,
|
|
712
|
+
obligation,
|
|
713
|
+
obligationKey,
|
|
714
|
+
coreIds.market,
|
|
715
|
+
coreIds.dmlR,
|
|
716
|
+
amount,
|
|
717
|
+
coreIds.oracle,
|
|
718
|
+
SUI_CLOCK_OBJECT_ID
|
|
719
|
+
],
|
|
720
|
+
[coinType]
|
|
721
|
+
);
|
|
722
|
+
},
|
|
723
|
+
repay: ({ txBlock, coreIds, scallopAddress, scallopUtils }) => (obligation, coin, coinName) => {
|
|
724
|
+
const coinPackageId = scallopAddress.get(`core.coins.${coinName}.id`);
|
|
725
|
+
const coinType = scallopUtils.parseCoinType(coinPackageId, coinName);
|
|
726
|
+
return txBlock.moveCall(
|
|
727
|
+
`${coreIds.protocolPkg}::repay::repay`,
|
|
728
|
+
[
|
|
729
|
+
coreIds.version,
|
|
730
|
+
obligation,
|
|
731
|
+
coreIds.market,
|
|
732
|
+
coin,
|
|
733
|
+
SUI_CLOCK_OBJECT_ID
|
|
734
|
+
],
|
|
735
|
+
[coinType]
|
|
736
|
+
);
|
|
737
|
+
},
|
|
738
|
+
borrowFlashLoan: ({ txBlock, coreIds, scallopAddress, scallopUtils }) => (amount, coinName) => {
|
|
739
|
+
const coinPackageId = scallopAddress.get(`core.coins.${coinName}.id`);
|
|
740
|
+
const coinType = scallopUtils.parseCoinType(coinPackageId, coinName);
|
|
741
|
+
return txBlock.moveCall(
|
|
742
|
+
`${coreIds.protocolPkg}::flash_loan::borrow_flash_loan`,
|
|
743
|
+
[coreIds.version, coreIds.market, amount],
|
|
744
|
+
[coinType]
|
|
745
|
+
);
|
|
746
|
+
},
|
|
747
|
+
repayFlashLoan: ({ txBlock, coreIds, scallopAddress, scallopUtils }) => (coin, loan, coinName) => {
|
|
748
|
+
const coinPackageId = scallopAddress.get(`core.coins.${coinName}.id`);
|
|
749
|
+
const coinType = scallopUtils.parseCoinType(coinPackageId, coinName);
|
|
750
|
+
return txBlock.moveCall(
|
|
751
|
+
`${coreIds.protocolPkg}::flash_loan::repay_flash_loan`,
|
|
752
|
+
[coreIds.version, coreIds.market, coin, loan],
|
|
753
|
+
[coinType]
|
|
754
|
+
);
|
|
755
|
+
}
|
|
756
|
+
};
|
|
757
|
+
var newTxBlock = (scallopAddress, scallopUtils) => {
|
|
758
|
+
const coreIds = {
|
|
759
|
+
protocolPkg: scallopAddress.get("core.packages.protocol.id"),
|
|
760
|
+
market: scallopAddress.get("core.market"),
|
|
761
|
+
version: scallopAddress.get("core.version"),
|
|
762
|
+
dmlR: scallopAddress.get("core.coinDecimalsRegistry"),
|
|
763
|
+
oracle: scallopAddress.get("core.oracles.xOracle")
|
|
764
|
+
};
|
|
765
|
+
const txBlock = new SuiTxBlock3();
|
|
766
|
+
const txBlockProxy = new Proxy(txBlock, {
|
|
767
|
+
get: (target, prop) => {
|
|
768
|
+
if (prop in scallopNormalMethodsHandler) {
|
|
769
|
+
return scallopNormalMethodsHandler[prop]({
|
|
770
|
+
txBlock: target,
|
|
771
|
+
coreIds,
|
|
772
|
+
scallopAddress,
|
|
773
|
+
scallopUtils
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
return target[prop];
|
|
777
|
+
}
|
|
778
|
+
});
|
|
779
|
+
return txBlockProxy;
|
|
780
|
+
};
|
|
781
|
+
|
|
782
|
+
// src/txBuilders/oracle.ts
|
|
783
|
+
import { fromB64 } from "@mysten/bcs";
|
|
784
|
+
import { SUI_CLOCK_OBJECT_ID as SUI_CLOCK_OBJECT_ID2 } from "@mysten/sui.js";
|
|
785
|
+
var updateOraclesForWithdrawCollateral = async (txBlock, address, scallopUtils, suiKit, obligationId, isTestnet) => {
|
|
786
|
+
const obligationCoinNames = await getObligationCoinNames(
|
|
787
|
+
suiKit,
|
|
788
|
+
obligationId,
|
|
789
|
+
address,
|
|
790
|
+
scallopUtils
|
|
791
|
+
);
|
|
792
|
+
return updateOracles(
|
|
793
|
+
txBlock,
|
|
794
|
+
address,
|
|
795
|
+
scallopUtils,
|
|
796
|
+
obligationCoinNames,
|
|
797
|
+
isTestnet
|
|
798
|
+
);
|
|
799
|
+
};
|
|
800
|
+
var updateOraclesForBorrow = async (txBlock, address, scallopUtils, suiKit, obligationId, borrowCoinName, isTestnet) => {
|
|
801
|
+
const obligationCoinNames = await getObligationCoinNames(
|
|
802
|
+
suiKit,
|
|
803
|
+
obligationId,
|
|
804
|
+
address,
|
|
805
|
+
scallopUtils
|
|
806
|
+
);
|
|
807
|
+
const updateCoinNames = [
|
|
808
|
+
.../* @__PURE__ */ new Set([...obligationCoinNames, borrowCoinName])
|
|
809
|
+
];
|
|
810
|
+
return updateOracles(
|
|
811
|
+
txBlock,
|
|
812
|
+
address,
|
|
813
|
+
scallopUtils,
|
|
814
|
+
updateCoinNames,
|
|
815
|
+
isTestnet
|
|
816
|
+
);
|
|
817
|
+
};
|
|
818
|
+
var getObligationCoinNames = async (suiKit, obligationId, address, scallopUtils) => {
|
|
819
|
+
const obligation = await queryObligation(obligationId, address, suiKit);
|
|
820
|
+
const collateralCoinTypes = obligation.collaterals.map((collateral) => {
|
|
821
|
+
return `0x${collateral.type.name}`;
|
|
822
|
+
});
|
|
823
|
+
const debtCoinTypes = obligation.debts.map((debt) => {
|
|
824
|
+
return `0x${debt.type.name}`;
|
|
825
|
+
});
|
|
826
|
+
const obligationCoinTypes = [
|
|
827
|
+
.../* @__PURE__ */ new Set([...collateralCoinTypes, ...debtCoinTypes])
|
|
828
|
+
];
|
|
829
|
+
const obligationCoinNames = obligationCoinTypes.map((coinType) => {
|
|
830
|
+
return scallopUtils.getCoinNameFromCoinType(coinType);
|
|
831
|
+
});
|
|
832
|
+
return obligationCoinNames;
|
|
833
|
+
};
|
|
834
|
+
var updateOracles = async (txBlock, address, scallopUtils, coinNames, isTestnet) => {
|
|
835
|
+
const updateCoinTypes = [...new Set(coinNames)];
|
|
836
|
+
for (const coinName of updateCoinTypes) {
|
|
837
|
+
await updateOracle(txBlock, address, scallopUtils, coinName, isTestnet);
|
|
838
|
+
}
|
|
839
|
+
};
|
|
840
|
+
var updateOracle = async (txBlock, address, scallopUtils, coinName, isTestnet) => {
|
|
841
|
+
const coinPackageId = address.get(`core.coins.${coinName}.id`);
|
|
842
|
+
const coinType = scallopUtils.parseCoinType(coinPackageId, coinName);
|
|
843
|
+
const [vaaFromFeeId] = await scallopUtils.getVaas(
|
|
844
|
+
[address.get(`core.coins.${coinName}.oracle.pyth.feed`)],
|
|
845
|
+
isTestnet
|
|
846
|
+
);
|
|
847
|
+
updatePrice(
|
|
848
|
+
txBlock,
|
|
849
|
+
isTestnet ? ["pyth"] : ["pyth"],
|
|
850
|
+
address.get("core.packages.xOracle.id"),
|
|
851
|
+
address.get("core.oracles.xOracle"),
|
|
852
|
+
address.get("core.packages.pyth.id"),
|
|
853
|
+
address.get("core.oracles.pyth.registry"),
|
|
854
|
+
address.get("core.oracles.pyth.state"),
|
|
855
|
+
address.get("core.oracles.pyth.wormholeState"),
|
|
856
|
+
address.get(`core.coins.${coinName}.oracle.pyth.feedObject`),
|
|
857
|
+
vaaFromFeeId,
|
|
858
|
+
address.get("core.packages.switchboard.id"),
|
|
859
|
+
address.get("core.oracles.switchboard.registry"),
|
|
860
|
+
address.get(`core.coins.${coinName}.oracle.switchboard`),
|
|
861
|
+
address.get("core.packages.supra.id"),
|
|
862
|
+
address.get("core.oracles.supra.registry"),
|
|
863
|
+
address.get(`core.oracles.supra.holder`),
|
|
864
|
+
coinType
|
|
865
|
+
);
|
|
866
|
+
};
|
|
867
|
+
function updatePrice(txBlock, rules, xOraclePackageId, xOracleId, pythPackageId, pythRegistryId, pythStateId, pythWormholeStateId, pythFeedObjectId, pythVaaFromFeeId, switchboardPackageId, switchboardRegistryId, switchboardAggregatorId, supraPackageId, supraRegistryId, supraHolderId, coinType) {
|
|
868
|
+
const request = priceUpdateRequest(
|
|
869
|
+
txBlock,
|
|
870
|
+
xOraclePackageId,
|
|
871
|
+
xOracleId,
|
|
872
|
+
coinType
|
|
873
|
+
);
|
|
874
|
+
if (rules.includes("pyth")) {
|
|
875
|
+
updatePythPrice(
|
|
876
|
+
txBlock,
|
|
877
|
+
pythPackageId,
|
|
878
|
+
request,
|
|
879
|
+
pythStateId,
|
|
880
|
+
pythWormholeStateId,
|
|
881
|
+
pythFeedObjectId,
|
|
882
|
+
pythVaaFromFeeId,
|
|
883
|
+
pythRegistryId,
|
|
884
|
+
coinType
|
|
885
|
+
);
|
|
886
|
+
}
|
|
887
|
+
if (rules.includes("switchboard")) {
|
|
888
|
+
updateSwitchboardPrice(
|
|
889
|
+
txBlock,
|
|
890
|
+
switchboardPackageId,
|
|
891
|
+
request,
|
|
892
|
+
switchboardAggregatorId,
|
|
893
|
+
switchboardRegistryId,
|
|
894
|
+
coinType
|
|
895
|
+
);
|
|
896
|
+
}
|
|
897
|
+
if (rules.includes("supra")) {
|
|
898
|
+
updateSupraPrice(
|
|
899
|
+
txBlock,
|
|
900
|
+
supraPackageId,
|
|
901
|
+
request,
|
|
902
|
+
supraHolderId,
|
|
903
|
+
supraRegistryId,
|
|
904
|
+
coinType
|
|
905
|
+
);
|
|
906
|
+
}
|
|
907
|
+
confirmPriceUpdateRequest(
|
|
908
|
+
txBlock,
|
|
909
|
+
xOraclePackageId,
|
|
910
|
+
xOracleId,
|
|
911
|
+
request,
|
|
912
|
+
coinType
|
|
913
|
+
);
|
|
914
|
+
return txBlock;
|
|
915
|
+
}
|
|
916
|
+
function priceUpdateRequest(txBlock, packageId, xOracleId, coinType) {
|
|
917
|
+
const target = `${packageId}::x_oracle::price_update_request`;
|
|
918
|
+
const typeArgs = [coinType];
|
|
919
|
+
return txBlock.moveCall(target, [xOracleId], typeArgs);
|
|
920
|
+
}
|
|
921
|
+
function confirmPriceUpdateRequest(txBlock, packageId, xOracleId, request, coinType) {
|
|
922
|
+
const target = `${packageId}::x_oracle::confirm_price_update_request`;
|
|
923
|
+
const typeArgs = [coinType];
|
|
924
|
+
txBlock.moveCall(target, [xOracleId, request, SUI_CLOCK_OBJECT_ID2], typeArgs);
|
|
925
|
+
return txBlock;
|
|
926
|
+
}
|
|
927
|
+
function updateSupraPrice(txBlock, packageId, request, holderId, registryId, coinType) {
|
|
928
|
+
txBlock.moveCall(
|
|
929
|
+
`${packageId}::rule::set_price`,
|
|
930
|
+
[request, holderId, registryId, SUI_CLOCK_OBJECT_ID2],
|
|
931
|
+
[coinType]
|
|
932
|
+
);
|
|
933
|
+
}
|
|
934
|
+
function updateSwitchboardPrice(txBlock, packageId, request, aggregatorId, registryId, coinType) {
|
|
935
|
+
txBlock.moveCall(
|
|
936
|
+
`${packageId}::rule::set_price`,
|
|
937
|
+
[request, aggregatorId, registryId, SUI_CLOCK_OBJECT_ID2],
|
|
938
|
+
[coinType]
|
|
939
|
+
);
|
|
940
|
+
}
|
|
941
|
+
function updatePythPrice(txBlock, packageId, request, stateId, wormholeStateId, feedObjectId, vaaFromFeeId, registryId, coinType) {
|
|
942
|
+
const [updateFee] = txBlock.splitSUIFromGas([1]);
|
|
943
|
+
txBlock.moveCall(
|
|
944
|
+
`${packageId}::rule::set_price`,
|
|
945
|
+
[
|
|
946
|
+
request,
|
|
947
|
+
wormholeStateId,
|
|
948
|
+
stateId,
|
|
949
|
+
feedObjectId,
|
|
950
|
+
registryId,
|
|
951
|
+
txBlock.pure([...fromB64(vaaFromFeeId)]),
|
|
952
|
+
updateFee,
|
|
953
|
+
SUI_CLOCK_OBJECT_ID2
|
|
954
|
+
],
|
|
955
|
+
[coinType]
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
// src/txBuilders/coin.ts
|
|
960
|
+
var selectCoin = async (txBlock, scallopAddress, scallopUtils, coinName, amount, sender) => {
|
|
961
|
+
const coinPackageId = scallopAddress.get(`core.coins.${coinName}.id`);
|
|
962
|
+
const coinType = scallopUtils.parseCoinType(coinPackageId, coinName);
|
|
963
|
+
const coins = await scallopUtils.selectCoins(sender, amount, coinType);
|
|
964
|
+
const [takeCoin, leftCoin] = txBlock.takeAmountFromCoins(coins, amount);
|
|
965
|
+
return { takeCoin, leftCoin };
|
|
966
|
+
};
|
|
967
|
+
var selectMarketCoin = async (txBlock, scallopAddress, scallopUtils, coinName, amount, sender) => {
|
|
968
|
+
const coinPackageId = scallopAddress.get(`core.coins.${coinName}.id`);
|
|
969
|
+
const protocolPackageId = scallopAddress.get("core.packages.protocol.id");
|
|
970
|
+
const coinType = scallopUtils.parseMarketCoinType(
|
|
971
|
+
coinPackageId,
|
|
972
|
+
protocolPackageId,
|
|
973
|
+
coinName
|
|
974
|
+
);
|
|
975
|
+
const coins = await scallopUtils.selectCoins(sender, amount, coinType);
|
|
976
|
+
const [takeCoin, leftCoin] = txBlock.takeAmountFromCoins(coins, amount);
|
|
977
|
+
return { takeCoin, leftCoin };
|
|
978
|
+
};
|
|
979
|
+
|
|
980
|
+
// src/txBuilders/quickMethods.ts
|
|
981
|
+
var requireSender = (txBlock) => {
|
|
982
|
+
const sender = txBlock.blockData.sender;
|
|
983
|
+
if (!sender) {
|
|
984
|
+
throw new Error("Sender is required");
|
|
985
|
+
}
|
|
986
|
+
return sender;
|
|
987
|
+
};
|
|
988
|
+
var requireObligationInfo = async (...args) => {
|
|
989
|
+
const [txBlock, scallopAddress, suiKit, obligationId, obligationKey] = args;
|
|
990
|
+
if (args.length === 4 && obligationId)
|
|
991
|
+
return { obligationId };
|
|
992
|
+
if (args.length === 5 && obligationId && obligationKey)
|
|
993
|
+
return { obligationId, obligationKey };
|
|
994
|
+
const sender = requireSender(txBlock);
|
|
995
|
+
const obligations = await getObligations(sender, scallopAddress, suiKit);
|
|
996
|
+
if (obligations.length === 0) {
|
|
997
|
+
throw new Error(`No obligation found for sender ${sender}`);
|
|
998
|
+
}
|
|
999
|
+
return {
|
|
1000
|
+
obligationId: obligations[0].id,
|
|
1001
|
+
obligationKey: obligations[0].keyId
|
|
1002
|
+
};
|
|
1003
|
+
};
|
|
1004
|
+
var scallopQuickMethodsHandler = {
|
|
1005
|
+
addCollateralQuick: ({ txBlock, scallopAddress, scallopUtils, suiKit }) => async (amount, coinName, obligationId) => {
|
|
1006
|
+
const sender = requireSender(txBlock);
|
|
1007
|
+
const { obligationId: obligationArg } = await requireObligationInfo(
|
|
1008
|
+
txBlock,
|
|
1009
|
+
scallopAddress,
|
|
1010
|
+
suiKit,
|
|
1011
|
+
obligationId
|
|
1012
|
+
);
|
|
1013
|
+
if (coinName === "sui") {
|
|
1014
|
+
const [suiCoin] = txBlock.splitSUIFromGas([amount]);
|
|
1015
|
+
txBlock.addCollateral(obligationArg, suiCoin, coinName);
|
|
1016
|
+
} else {
|
|
1017
|
+
const { leftCoin, takeCoin } = await selectCoin(
|
|
1018
|
+
txBlock,
|
|
1019
|
+
scallopAddress,
|
|
1020
|
+
scallopUtils,
|
|
1021
|
+
coinName,
|
|
1022
|
+
amount,
|
|
1023
|
+
sender
|
|
1024
|
+
);
|
|
1025
|
+
txBlock.addCollateral(obligationArg, takeCoin, coinName);
|
|
1026
|
+
txBlock.transferObjects([leftCoin], sender);
|
|
1027
|
+
}
|
|
1028
|
+
},
|
|
1029
|
+
takeCollateralQuick: ({ txBlock, suiKit, scallopUtils, scallopAddress, isTestnet }) => async (amount, coinName, obligationId, obligationKey) => {
|
|
1030
|
+
const { obligationId: obligationArg, obligationKey: obligationKeyArg } = await requireObligationInfo(
|
|
1031
|
+
txBlock,
|
|
1032
|
+
scallopAddress,
|
|
1033
|
+
suiKit,
|
|
1034
|
+
obligationId,
|
|
1035
|
+
obligationKey
|
|
1036
|
+
);
|
|
1037
|
+
await updateOraclesForWithdrawCollateral(
|
|
1038
|
+
txBlock,
|
|
1039
|
+
scallopAddress,
|
|
1040
|
+
scallopUtils,
|
|
1041
|
+
suiKit,
|
|
1042
|
+
obligationArg,
|
|
1043
|
+
isTestnet
|
|
1044
|
+
);
|
|
1045
|
+
return txBlock.takeCollateral(
|
|
1046
|
+
obligationArg,
|
|
1047
|
+
obligationKeyArg,
|
|
1048
|
+
amount,
|
|
1049
|
+
coinName
|
|
1050
|
+
);
|
|
1051
|
+
},
|
|
1052
|
+
depositQuick: ({ txBlock, scallopUtils, scallopAddress }) => async (amount, coinName) => {
|
|
1053
|
+
const sender = requireSender(txBlock);
|
|
1054
|
+
if (coinName === "sui") {
|
|
1055
|
+
const [suiCoin] = txBlock.splitSUIFromGas([amount]);
|
|
1056
|
+
return txBlock.deposit(suiCoin, coinName);
|
|
1057
|
+
} else {
|
|
1058
|
+
const { leftCoin, takeCoin } = await selectCoin(
|
|
1059
|
+
txBlock,
|
|
1060
|
+
scallopAddress,
|
|
1061
|
+
scallopUtils,
|
|
1062
|
+
coinName,
|
|
1063
|
+
amount,
|
|
1064
|
+
sender
|
|
1065
|
+
);
|
|
1066
|
+
txBlock.transferObjects([leftCoin], sender);
|
|
1067
|
+
return txBlock.deposit(takeCoin, coinName);
|
|
1068
|
+
}
|
|
1069
|
+
},
|
|
1070
|
+
withdrawQuick: ({ txBlock, scallopUtils, scallopAddress }) => async (amount, coinName) => {
|
|
1071
|
+
const sender = requireSender(txBlock);
|
|
1072
|
+
const { leftCoin, takeCoin } = await selectMarketCoin(
|
|
1073
|
+
txBlock,
|
|
1074
|
+
scallopAddress,
|
|
1075
|
+
scallopUtils,
|
|
1076
|
+
coinName,
|
|
1077
|
+
amount,
|
|
1078
|
+
sender
|
|
1079
|
+
);
|
|
1080
|
+
txBlock.transferObjects([leftCoin], sender);
|
|
1081
|
+
return txBlock.withdraw(takeCoin, coinName);
|
|
1082
|
+
},
|
|
1083
|
+
borrowQuick: ({ txBlock, suiKit, scallopUtils, scallopAddress, isTestnet }) => async (amount, coinName, obligationId, obligationKey) => {
|
|
1084
|
+
const { obligationId: obligationArg, obligationKey: obligationKeyArg } = await requireObligationInfo(
|
|
1085
|
+
txBlock,
|
|
1086
|
+
scallopAddress,
|
|
1087
|
+
suiKit,
|
|
1088
|
+
obligationId,
|
|
1089
|
+
obligationKey
|
|
1090
|
+
);
|
|
1091
|
+
await updateOraclesForBorrow(
|
|
1092
|
+
txBlock,
|
|
1093
|
+
scallopAddress,
|
|
1094
|
+
scallopUtils,
|
|
1095
|
+
suiKit,
|
|
1096
|
+
obligationArg,
|
|
1097
|
+
coinName,
|
|
1098
|
+
isTestnet
|
|
1099
|
+
);
|
|
1100
|
+
return txBlock.borrow(
|
|
1101
|
+
obligationArg,
|
|
1102
|
+
obligationKeyArg,
|
|
1103
|
+
amount,
|
|
1104
|
+
coinName
|
|
1105
|
+
);
|
|
1106
|
+
},
|
|
1107
|
+
repayQuick: ({ txBlock, suiKit, scallopUtils, scallopAddress }) => async (amount, coinName, obligationId) => {
|
|
1108
|
+
const sender = requireSender(txBlock);
|
|
1109
|
+
const { obligationId: obligationArg } = await requireObligationInfo(
|
|
1110
|
+
txBlock,
|
|
1111
|
+
scallopAddress,
|
|
1112
|
+
suiKit,
|
|
1113
|
+
obligationId
|
|
1114
|
+
);
|
|
1115
|
+
if (coinName === "sui") {
|
|
1116
|
+
const [suiCoin] = txBlock.splitSUIFromGas([amount]);
|
|
1117
|
+
return txBlock.repay(obligationArg, suiCoin, coinName);
|
|
1118
|
+
} else {
|
|
1119
|
+
const { leftCoin, takeCoin } = await selectCoin(
|
|
1120
|
+
txBlock,
|
|
1121
|
+
scallopAddress,
|
|
1122
|
+
scallopUtils,
|
|
1123
|
+
coinName,
|
|
1124
|
+
amount,
|
|
1125
|
+
sender
|
|
1126
|
+
);
|
|
1127
|
+
txBlock.transferObjects([leftCoin], sender);
|
|
1128
|
+
return txBlock.repay(obligationArg, takeCoin, coinName);
|
|
1129
|
+
}
|
|
1130
|
+
},
|
|
1131
|
+
updateAssetPricesQuick: ({ txBlock, scallopUtils, scallopAddress, isTestnet }) => async (coinNames) => {
|
|
1132
|
+
return updateOracles(
|
|
1133
|
+
txBlock,
|
|
1134
|
+
scallopAddress,
|
|
1135
|
+
scallopUtils,
|
|
1136
|
+
coinNames,
|
|
1137
|
+
isTestnet
|
|
1138
|
+
);
|
|
1139
|
+
}
|
|
1140
|
+
};
|
|
1141
|
+
var newScallopTxBlock = (suiKit, scallopAddress, scallopUtils, isTestnet) => {
|
|
1142
|
+
const txBlock = newTxBlock(scallopAddress, scallopUtils);
|
|
1143
|
+
const txBlockProxy = new Proxy(txBlock, {
|
|
1144
|
+
get: (target, prop) => {
|
|
1145
|
+
if (prop in scallopQuickMethodsHandler) {
|
|
1146
|
+
return scallopQuickMethodsHandler[prop]({
|
|
1147
|
+
txBlock: target,
|
|
1148
|
+
suiKit,
|
|
1149
|
+
scallopAddress,
|
|
1150
|
+
scallopUtils,
|
|
1151
|
+
isTestnet
|
|
1152
|
+
});
|
|
1153
|
+
}
|
|
1154
|
+
return target[prop];
|
|
1155
|
+
}
|
|
1156
|
+
});
|
|
1157
|
+
return txBlockProxy;
|
|
1158
|
+
};
|
|
1159
|
+
|
|
1160
|
+
// src/models/scallopClient.ts
|
|
1161
|
+
var ScallopClient = class {
|
|
1162
|
+
constructor(params, address, walletAddress, isTestnet) {
|
|
1163
|
+
this.suiKit = new SuiKit4(params);
|
|
1164
|
+
this.address = address;
|
|
1165
|
+
this.walletAddress = normalizeSuiAddress(
|
|
1166
|
+
walletAddress || this.suiKit.currentAddress()
|
|
1167
|
+
);
|
|
1168
|
+
this._utils = new ScallopUtils(params);
|
|
1169
|
+
this._isTestnet = isTestnet || (params.networkType ? params.networkType === "testnet" : false);
|
|
1170
|
+
}
|
|
1171
|
+
createTxBlock() {
|
|
1172
|
+
return newScallopTxBlock(
|
|
1173
|
+
this.suiKit,
|
|
1174
|
+
this.address,
|
|
1175
|
+
this._utils,
|
|
1176
|
+
this._isTestnet
|
|
1177
|
+
);
|
|
1178
|
+
}
|
|
1179
|
+
/**
|
|
1180
|
+
* Query market data.
|
|
1181
|
+
*
|
|
1182
|
+
* @return Market data
|
|
1183
|
+
*/
|
|
1184
|
+
async queryMarket() {
|
|
1185
|
+
return queryMarket(this.address, this.suiKit);
|
|
1186
|
+
}
|
|
1187
|
+
/**
|
|
1188
|
+
* Query obligations data.
|
|
1189
|
+
*
|
|
1190
|
+
* @param ownerAddress - The owner address.
|
|
1191
|
+
* @return Obligations data
|
|
1192
|
+
*/
|
|
1193
|
+
async getObligations(ownerAddress) {
|
|
1194
|
+
const owner = ownerAddress || this.walletAddress;
|
|
1195
|
+
return getObligations(owner, this.address, this.suiKit);
|
|
1196
|
+
}
|
|
1197
|
+
/**
|
|
1198
|
+
* Query obligation data.
|
|
1199
|
+
*
|
|
1200
|
+
* @param obligationId - The obligation id from protocol package.
|
|
1201
|
+
* @return Obligation data
|
|
1202
|
+
*/
|
|
1203
|
+
async queryObligation(obligationId) {
|
|
1204
|
+
return queryObligation(obligationId, this.address, this.suiKit);
|
|
1205
|
+
}
|
|
1206
|
+
async openObligation(sign = true) {
|
|
1207
|
+
const txBlock = this.createTxBlock();
|
|
1208
|
+
txBlock.openObligationEntry();
|
|
1209
|
+
if (sign) {
|
|
1210
|
+
return await this.suiKit.signAndSendTxn(
|
|
1211
|
+
txBlock
|
|
1212
|
+
);
|
|
1213
|
+
} else {
|
|
1214
|
+
return txBlock.txBlock;
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
async depositCollateral(coinName, amount, sign = true, obligationId, walletAddress) {
|
|
1218
|
+
const txBlock = this.createTxBlock();
|
|
1219
|
+
const sender = walletAddress || this.walletAddress;
|
|
1220
|
+
txBlock.setSender(sender);
|
|
1221
|
+
if (obligationId) {
|
|
1222
|
+
await txBlock.addCollateralQuick(amount, coinName, obligationId);
|
|
1223
|
+
} else {
|
|
1224
|
+
const [obligation, obligationKey, hotPotato] = txBlock.openObligation();
|
|
1225
|
+
await txBlock.addCollateralQuick(amount, coinName, obligation);
|
|
1226
|
+
txBlock.returnObligation(obligation, hotPotato);
|
|
1227
|
+
txBlock.transferObjects([obligationKey], sender);
|
|
1228
|
+
}
|
|
1229
|
+
if (sign) {
|
|
1230
|
+
return await this.suiKit.signAndSendTxn(
|
|
1231
|
+
txBlock
|
|
1232
|
+
);
|
|
1233
|
+
} else {
|
|
1234
|
+
return txBlock.txBlock;
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
/**
|
|
1238
|
+
* Withdraw collateral from the specific pool.
|
|
1239
|
+
*
|
|
1240
|
+
* @param coinName - Types of collateral coin.
|
|
1241
|
+
* @param amount - The amount of coins would deposit.
|
|
1242
|
+
* @param sign - Decide to directly sign the transaction or return the transaction block.
|
|
1243
|
+
* @param obligationId - The obligation object.
|
|
1244
|
+
* @param obligationKey - The obligation key object to verifying obligation authority.
|
|
1245
|
+
* @param walletAddress - The wallet address of the owner.
|
|
1246
|
+
* @return Transaction block response or transaction block
|
|
1247
|
+
*/
|
|
1248
|
+
async withdrawCollateral(coinName, amount, sign = true, obligationId, obligationKey, walletAddress) {
|
|
1249
|
+
const txBlock = this.createTxBlock();
|
|
1250
|
+
const sender = walletAddress || this.walletAddress;
|
|
1251
|
+
txBlock.setSender(sender);
|
|
1252
|
+
const collateralCoin = await txBlock.takeCollateralQuick(
|
|
1253
|
+
amount,
|
|
1254
|
+
coinName,
|
|
1255
|
+
obligationId,
|
|
1256
|
+
obligationKey
|
|
1257
|
+
);
|
|
1258
|
+
txBlock.transferObjects([collateralCoin], sender);
|
|
1259
|
+
if (sign) {
|
|
1260
|
+
return await this.suiKit.signAndSendTxn(
|
|
1261
|
+
txBlock
|
|
1262
|
+
);
|
|
1263
|
+
} else {
|
|
1264
|
+
return txBlock.txBlock;
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
async deposit(coinName, amount, sign = true, walletAddress) {
|
|
1268
|
+
const txBlock = this.createTxBlock();
|
|
1269
|
+
const sender = walletAddress || this.walletAddress;
|
|
1270
|
+
txBlock.setSender(sender);
|
|
1271
|
+
const marketCoin = await txBlock.depositQuick(amount, coinName);
|
|
1272
|
+
txBlock.transferObjects([marketCoin], sender);
|
|
1273
|
+
if (sign) {
|
|
1274
|
+
return await this.suiKit.signAndSendTxn(
|
|
1275
|
+
txBlock
|
|
1276
|
+
);
|
|
1277
|
+
} else {
|
|
1278
|
+
return txBlock.txBlock;
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
async withdraw(coinName, amount, sign = true, walletAddress) {
|
|
1282
|
+
const txBlock = this.createTxBlock();
|
|
1283
|
+
const sender = walletAddress || this.walletAddress;
|
|
1284
|
+
txBlock.setSender(sender);
|
|
1285
|
+
const coin = await txBlock.withdrawQuick(amount, coinName);
|
|
1286
|
+
txBlock.transferObjects([coin], sender);
|
|
1287
|
+
if (sign) {
|
|
1288
|
+
return await this.suiKit.signAndSendTxn(
|
|
1289
|
+
txBlock
|
|
1290
|
+
);
|
|
1291
|
+
} else {
|
|
1292
|
+
return txBlock.txBlock;
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
/**
|
|
1296
|
+
* borrow asset from the specific pool.
|
|
1297
|
+
*
|
|
1298
|
+
* @param coinName - Types of asset coin.
|
|
1299
|
+
* @param amount - The amount of coins would borrow.
|
|
1300
|
+
* @param sign - Decide to directly sign the transaction or return the transaction block.
|
|
1301
|
+
* @param obligationId - The obligation object.
|
|
1302
|
+
* @param obligationKey - The obligation key object to verifying obligation authority.
|
|
1303
|
+
* @param walletAddress - The wallet address of the owner.
|
|
1304
|
+
* @return Transaction block response or transaction block
|
|
1305
|
+
*/
|
|
1306
|
+
async borrow(coinName, amount, sign = true, obligationId, obligationKey, walletAddress) {
|
|
1307
|
+
const txBlock = this.createTxBlock();
|
|
1308
|
+
const sender = walletAddress || this.walletAddress;
|
|
1309
|
+
txBlock.setSender(sender);
|
|
1310
|
+
const coin = await txBlock.borrowQuick(
|
|
1311
|
+
amount,
|
|
1312
|
+
coinName,
|
|
1313
|
+
obligationId,
|
|
1314
|
+
obligationKey
|
|
1315
|
+
);
|
|
1316
|
+
txBlock.transferObjects([coin], sender);
|
|
1317
|
+
if (sign) {
|
|
1318
|
+
return await this.suiKit.signAndSendTxn(
|
|
1319
|
+
txBlock
|
|
1320
|
+
);
|
|
1321
|
+
} else {
|
|
1322
|
+
return txBlock.txBlock;
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
/**
|
|
1326
|
+
* Repay asset into the specific pool.
|
|
1327
|
+
*
|
|
1328
|
+
* @param coinName - Types of asset coin.
|
|
1329
|
+
* @param amount - The amount of coins would repay.
|
|
1330
|
+
* @param sign - Decide to directly sign the transaction or return the transaction block.
|
|
1331
|
+
* @param obligationId - The obligation object.
|
|
1332
|
+
* @param walletAddress - The wallet address of the owner.
|
|
1333
|
+
* @return Transaction block response or transaction block
|
|
1334
|
+
*/
|
|
1335
|
+
async repay(coinName, amount, sign = true, obligationId, walletAddress) {
|
|
1336
|
+
const txBlock = this.createTxBlock();
|
|
1337
|
+
const sender = walletAddress || this.walletAddress;
|
|
1338
|
+
txBlock.setSender(sender);
|
|
1339
|
+
await txBlock.repayQuick(amount, coinName, obligationId);
|
|
1340
|
+
if (sign) {
|
|
1341
|
+
return await this.suiKit.signAndSendTxn(
|
|
1342
|
+
txBlock
|
|
1343
|
+
);
|
|
1344
|
+
} else {
|
|
1345
|
+
return txBlock.txBlock;
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
async flashLoan(coinName, amount, callback, sign = true) {
|
|
1349
|
+
const txBlock = this.createTxBlock();
|
|
1350
|
+
const [coin, loan] = txBlock.borrowFlashLoan(amount, coinName);
|
|
1351
|
+
txBlock.repayFlashLoan(callback(txBlock, coin), loan, coinName);
|
|
1352
|
+
if (sign) {
|
|
1353
|
+
return await this.suiKit.signAndSendTxn(
|
|
1354
|
+
txBlock
|
|
1355
|
+
);
|
|
1356
|
+
} else {
|
|
1357
|
+
return txBlock.txBlock;
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
async mintTestCoin(coinName, amount, sign = true, receiveAddress) {
|
|
1361
|
+
if (!this._isTestnet) {
|
|
1362
|
+
throw new Error("Only be used on the test network.");
|
|
1363
|
+
}
|
|
1364
|
+
const txBlock = this.createTxBlock();
|
|
1365
|
+
const recipient = receiveAddress || this.walletAddress;
|
|
1366
|
+
const packageId = this.address.get("core.packages.testCoin.id");
|
|
1367
|
+
const treasuryId = this.address.get(`core.coins.${coinName}.treasury`);
|
|
1368
|
+
const target = `${packageId}::${coinName}::mint`;
|
|
1369
|
+
const coin = txBlock.moveCall(target, [treasuryId, amount]);
|
|
1370
|
+
txBlock.transferObjects([coin], recipient);
|
|
1371
|
+
if (sign) {
|
|
1372
|
+
return await this.suiKit.signAndSendTxn(
|
|
1373
|
+
txBlock
|
|
1374
|
+
);
|
|
1375
|
+
} else {
|
|
1376
|
+
return txBlock.txBlock;
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
};
|
|
1380
|
+
|
|
1381
|
+
// src/models/scallop.ts
|
|
1382
|
+
var Scallop = class {
|
|
1383
|
+
constructor(params) {
|
|
1384
|
+
this.params = params;
|
|
1385
|
+
this.suiKit = new SuiKit5(params);
|
|
1386
|
+
this.address = new ScallopAddress({
|
|
1387
|
+
id: ADDRESSES_ID,
|
|
1388
|
+
network: params?.networkType
|
|
1389
|
+
});
|
|
1390
|
+
}
|
|
1391
|
+
/**
|
|
1392
|
+
* Create an instance to operate the transaction block, making it more convenient to organize transaction combinations.
|
|
1393
|
+
* @return Scallop Transaction Builder
|
|
1394
|
+
*/
|
|
1395
|
+
async createTxBuilder() {
|
|
1396
|
+
await this.address.read();
|
|
1397
|
+
const scallopUtils = new ScallopUtils(this.params);
|
|
1398
|
+
const suiKit = new SuiKit5(this.params);
|
|
1399
|
+
const isTestnet = this.params.networkType === "testnet";
|
|
1400
|
+
return {
|
|
1401
|
+
createTxBlock: () => {
|
|
1402
|
+
return newScallopTxBlock(suiKit, this.address, scallopUtils, isTestnet);
|
|
1403
|
+
},
|
|
1404
|
+
signAndSendTxBlock: (txBlock) => {
|
|
1405
|
+
return suiKit.signAndSendTxn(txBlock);
|
|
1406
|
+
}
|
|
1407
|
+
};
|
|
1408
|
+
}
|
|
1409
|
+
/**
|
|
1410
|
+
* Create an instance to collect the addresses, making it easier to get object addresses from lending contract.
|
|
1411
|
+
*
|
|
1412
|
+
* @param id - The API id of the addresses.
|
|
1413
|
+
* @param auth - The authentication API key.
|
|
1414
|
+
* @param network - Specifies which network's addresses you want to set.
|
|
1415
|
+
* @return Scallop Address
|
|
1416
|
+
*/
|
|
1417
|
+
createAddress(id, auth, network) {
|
|
1418
|
+
return new ScallopAddress({ id, auth, network });
|
|
1419
|
+
}
|
|
1420
|
+
/**
|
|
1421
|
+
* Create an instance that provides contract interaction operations for general users.
|
|
1422
|
+
*
|
|
1423
|
+
* @param walletAddress - When user cannot provide a secret key or mnemonic, the scallop client cannot directly derive the address of the transaction the user wants to sign. This argument specifies the wallet address for signing the transaction.
|
|
1424
|
+
* @return Scallop Client
|
|
1425
|
+
*/
|
|
1426
|
+
async createScallopClient(walletAddress) {
|
|
1427
|
+
await this.address.read();
|
|
1428
|
+
return new ScallopClient(this.params, this.address, walletAddress);
|
|
1429
|
+
}
|
|
1430
|
+
};
|
|
1431
|
+
export {
|
|
1432
|
+
ADDRESSES_ID,
|
|
1433
|
+
API_BASE_URL,
|
|
1434
|
+
SUI_COIN_TYPE_ARG_REGEX,
|
|
1435
|
+
SUPPORT_ASSET_COINS,
|
|
1436
|
+
SUPPORT_COLLATERAL_COINS,
|
|
1437
|
+
SUPPORT_ORACLES,
|
|
1438
|
+
SUPPORT_PACKAGES,
|
|
1439
|
+
Scallop,
|
|
1440
|
+
ScallopAddress,
|
|
1441
|
+
ScallopClient,
|
|
1442
|
+
ScallopUtils
|
|
1443
|
+
};
|
|
1444
|
+
//# sourceMappingURL=index.mjs.map
|