@ultrade/ultrade-js-sdk 0.2.7 → 2.0.1
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/index.js +11 -19
- package/dist/src/algodService.d.ts +35 -0
- package/dist/src/client.d.ts +143 -0
- package/dist/src/enums.d.ts +34 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/interfaces.d.ts +136 -0
- package/dist/src/localStorage.d.ts +9 -0
- package/dist/src/sockets.d.ts +30 -0
- package/dist/src/utils.d.ts +2 -0
- package/package.json +28 -39
- package/README.md +0 -39
- package/dist/amm.d.ts +0 -345
- package/dist/amm.js +0 -1295
- package/dist/artifacts/master.d.ts +0 -14
- package/dist/artifacts/master.js +0 -89
- package/dist/artifacts/pool.d.ts +0 -25
- package/dist/artifacts/pool.js +0 -123
- package/dist/artifacts/stable.d.ts +0 -25
- package/dist/artifacts/stable.js +0 -155
- package/dist/constants.d.ts +0 -6
- package/dist/constants.js +0 -9
- package/dist/index.d.ts +0 -3
- package/dist/types.d.ts +0 -57
- package/dist/types.js +0 -2
- package/dist/utils.d.ts +0 -4
- package/dist/utils.js +0 -53
package/dist/amm.js
DELETED
|
@@ -1,1295 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.AmmClient = exports.PendingTxnResponse = void 0;
|
|
16
|
-
const algosdk_1 = __importDefault(require("algosdk"));
|
|
17
|
-
const master_1 = require("./artifacts/master");
|
|
18
|
-
const pool_1 = require("./artifacts/pool");
|
|
19
|
-
const stable_1 = require("./artifacts/stable");
|
|
20
|
-
const constants_1 = require("./constants");
|
|
21
|
-
const utils_1 = require("./utils");
|
|
22
|
-
class PendingTxnResponse {
|
|
23
|
-
constructor(response) {
|
|
24
|
-
this.poolError = response['pool-error'];
|
|
25
|
-
this.txn = response['txn'];
|
|
26
|
-
this.applicationIndex = response['application-index'];
|
|
27
|
-
this.assetIndex = response['asset-index'];
|
|
28
|
-
this.closeRewards = response['closing-rewards'];
|
|
29
|
-
this.closingAmount = response['closing-amount'];
|
|
30
|
-
this.confirmedRound = response['confirmed-round'];
|
|
31
|
-
this.globalStateDelta = response['global-state-delta'];
|
|
32
|
-
this.localStateDelta = response['local-state-delta'];
|
|
33
|
-
this.receiverRewards = response['receiver-rewards'];
|
|
34
|
-
this.senderRewards = response['sender-rewards'];
|
|
35
|
-
this.innerTxns = response['inner-txns'] ? response['inner-txns'] : [];
|
|
36
|
-
this.logs = response['logs'] ? response['logs'] : [];
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
exports.PendingTxnResponse = PendingTxnResponse;
|
|
40
|
-
class AmmClient {
|
|
41
|
-
/**
|
|
42
|
-
* construct AmmClient
|
|
43
|
-
*
|
|
44
|
-
* @param appId master app id
|
|
45
|
-
* @param cluster one of node
|
|
46
|
-
*/
|
|
47
|
-
constructor(appId, client) {
|
|
48
|
-
this.client = client;
|
|
49
|
-
this.appId = appId;
|
|
50
|
-
this.masterContract = new algosdk_1.default.ABIContract(master_1.MASTER_ABI);
|
|
51
|
-
this.poolContract = new algosdk_1.default.ABIContract(pool_1.POOL_ABI);
|
|
52
|
-
this.stableContract = new algosdk_1.default.ABIContract(stable_1.STABLE_ABI);
|
|
53
|
-
this.assetsCache = {};
|
|
54
|
-
this.poolsCache = {};
|
|
55
|
-
}
|
|
56
|
-
getAssetCache() {
|
|
57
|
-
return this.assetsCache;
|
|
58
|
-
}
|
|
59
|
-
getPoolsCache() {
|
|
60
|
-
return this.poolsCache;
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* get status of current node.
|
|
64
|
-
*
|
|
65
|
-
* @returns
|
|
66
|
-
*/
|
|
67
|
-
getStatus() {
|
|
68
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
69
|
-
const status = yield this.client.status().do();
|
|
70
|
-
return status;
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* check if an asset is stable coin.
|
|
75
|
-
*
|
|
76
|
-
* @returns
|
|
77
|
-
*/
|
|
78
|
-
isStableAsset(asset) {
|
|
79
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
80
|
-
try {
|
|
81
|
-
const boxName = algosdk_1.default.encodeUint64(asset);
|
|
82
|
-
const box = yield this.client
|
|
83
|
-
.getApplicationBoxByName(this.appId, boxName)
|
|
84
|
-
.do();
|
|
85
|
-
const flag = algosdk_1.default.decodeUint64(box.value, 'safe');
|
|
86
|
-
return flag != 0;
|
|
87
|
-
}
|
|
88
|
-
catch (e) {
|
|
89
|
-
return false;
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Returns the common needed parameters for a new transaction.
|
|
95
|
-
*
|
|
96
|
-
* @returns
|
|
97
|
-
*/
|
|
98
|
-
getTransactionParams() {
|
|
99
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
100
|
-
const params = yield this.client.getTransactionParams().do();
|
|
101
|
-
return params;
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* returns Algodv2 instance.
|
|
106
|
-
*
|
|
107
|
-
* @returns
|
|
108
|
-
*/
|
|
109
|
-
getAlgodClient() {
|
|
110
|
-
return this.client;
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* create a pool for asset A and B.
|
|
114
|
-
*
|
|
115
|
-
* @param sender the sender of transaction
|
|
116
|
-
* @param assetA
|
|
117
|
-
* @param assetB
|
|
118
|
-
* @returns
|
|
119
|
-
*/
|
|
120
|
-
createPair(sender, assetA, assetB, signer) {
|
|
121
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
122
|
-
if (assetA > assetB)
|
|
123
|
-
[assetA, assetB] = [assetB, assetA];
|
|
124
|
-
const isPoolExist = yield this.checkIsPoolExist(assetA, assetB);
|
|
125
|
-
if (isPoolExist) {
|
|
126
|
-
throw new Error('pool already created');
|
|
127
|
-
}
|
|
128
|
-
try {
|
|
129
|
-
const f1 = yield this.isStableAsset(assetA);
|
|
130
|
-
const f2 = yield this.isStableAsset(assetB);
|
|
131
|
-
let tmpPoolId;
|
|
132
|
-
if (f1 && f2) {
|
|
133
|
-
tmpPoolId = yield this.getTmpStablePoolId();
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
tmpPoolId = yield this.getTmpPoolId();
|
|
137
|
-
}
|
|
138
|
-
const atc = new algosdk_1.default.AtomicTransactionComposer();
|
|
139
|
-
const sp = yield this.client.getTransactionParams().do();
|
|
140
|
-
const boxName = new Uint8Array([
|
|
141
|
-
...algosdk_1.default.encodeUint64(assetA),
|
|
142
|
-
...algosdk_1.default.encodeUint64(assetB)
|
|
143
|
-
]);
|
|
144
|
-
const appInfo = yield this.client
|
|
145
|
-
.getApplicationByID(this.appId)
|
|
146
|
-
.do();
|
|
147
|
-
const appCreator = appInfo.params.creator;
|
|
148
|
-
atc.addMethodCall({
|
|
149
|
-
appID: this.appId,
|
|
150
|
-
method: (0, utils_1.getMethodByName)(this.masterContract, 'create_pool'),
|
|
151
|
-
methodArgs: [
|
|
152
|
-
{
|
|
153
|
-
txn: algosdk_1.default.makePaymentTxnWithSuggestedParamsFromObject({
|
|
154
|
-
from: sender,
|
|
155
|
-
suggestedParams: sp,
|
|
156
|
-
to: algosdk_1.default.getApplicationAddress(this.appId),
|
|
157
|
-
amount: 3324100
|
|
158
|
-
}),
|
|
159
|
-
signer
|
|
160
|
-
},
|
|
161
|
-
assetA,
|
|
162
|
-
assetB
|
|
163
|
-
],
|
|
164
|
-
appForeignApps: [tmpPoolId],
|
|
165
|
-
appForeignAssets: [assetA, assetB],
|
|
166
|
-
appAccounts: [appCreator],
|
|
167
|
-
boxes: [
|
|
168
|
-
{ appIndex: this.appId, name: boxName },
|
|
169
|
-
{
|
|
170
|
-
appIndex: this.appId,
|
|
171
|
-
name: algosdk_1.default.encodeUint64(assetA)
|
|
172
|
-
},
|
|
173
|
-
{ appIndex: this.appId, name: algosdk_1.default.encodeUint64(assetB) }
|
|
174
|
-
],
|
|
175
|
-
sender: sender,
|
|
176
|
-
suggestedParams: Object.assign(Object.assign({}, sp), { flatFee: true, fee: 12000 }),
|
|
177
|
-
signer
|
|
178
|
-
});
|
|
179
|
-
const res = yield atc.execute(this.client, 4);
|
|
180
|
-
return res;
|
|
181
|
-
}
|
|
182
|
-
catch (e) {
|
|
183
|
-
throw new Error('create pair failed: ' + e.message);
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
|
-
* Add liquidity to A-B pool
|
|
189
|
-
*
|
|
190
|
-
* @param sender the sender of transaction
|
|
191
|
-
* @param aId id of asset A to send the A-B pool
|
|
192
|
-
* @param aAmt amount of asset A
|
|
193
|
-
* @param bId id of asset B
|
|
194
|
-
* @param bAmt amount of asset B to send the A-B pool
|
|
195
|
-
* @param mintAmt
|
|
196
|
-
* @returns
|
|
197
|
-
*/
|
|
198
|
-
addLiquidity(sender, aId, aAmt, bId, bAmt, mintAmt, signer) {
|
|
199
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
200
|
-
if (aId > bId) {
|
|
201
|
-
[aId, bId] = [bId, aId];
|
|
202
|
-
[aAmt, bAmt] = [bAmt, aAmt];
|
|
203
|
-
}
|
|
204
|
-
if (aAmt <= 1000 || bAmt <= 1000) {
|
|
205
|
-
throw new Error('too small amount');
|
|
206
|
-
}
|
|
207
|
-
const poolId = yield this.getPoolIdByAssets(aId, bId);
|
|
208
|
-
const state = yield this.getPoolState(poolId);
|
|
209
|
-
if (state['a'] != aId || state['b'] != bId) {
|
|
210
|
-
throw new Error('incorrect pair');
|
|
211
|
-
}
|
|
212
|
-
const params = yield this.client.getTransactionParams().do();
|
|
213
|
-
const poolAddress = algosdk_1.default.getApplicationAddress(poolId);
|
|
214
|
-
const poolToken = state['p'];
|
|
215
|
-
const atc = new algosdk_1.default.AtomicTransactionComposer();
|
|
216
|
-
if (!(yield this.isOptedInAsset(poolToken, sender))) {
|
|
217
|
-
atc.addTransaction({
|
|
218
|
-
txn: algosdk_1.default.makeAssetTransferTxnWithSuggestedParamsFromObject({
|
|
219
|
-
from: sender,
|
|
220
|
-
suggestedParams: params,
|
|
221
|
-
to: sender,
|
|
222
|
-
amount: 0,
|
|
223
|
-
assetIndex: poolToken
|
|
224
|
-
}),
|
|
225
|
-
signer
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
const sp = yield this.client.getTransactionParams().do();
|
|
229
|
-
const firstMint = state['ra'] == 0 && state['rb'] == 0;
|
|
230
|
-
const sf1 = yield this.isStableAsset(aId);
|
|
231
|
-
const sf2 = yield this.isStableAsset(bId);
|
|
232
|
-
if (firstMint) {
|
|
233
|
-
if (aId == 0) {
|
|
234
|
-
atc.addMethodCall({
|
|
235
|
-
sender,
|
|
236
|
-
appID: poolId,
|
|
237
|
-
method: (0, utils_1.getMethodByName)(this.poolContract, 'fund'),
|
|
238
|
-
methodArgs: [
|
|
239
|
-
{
|
|
240
|
-
txn: algosdk_1.default.makePaymentTxnWithSuggestedParamsFromObject({
|
|
241
|
-
from: sender,
|
|
242
|
-
suggestedParams: sp,
|
|
243
|
-
to: poolAddress,
|
|
244
|
-
amount: aAmt
|
|
245
|
-
}),
|
|
246
|
-
signer
|
|
247
|
-
},
|
|
248
|
-
{
|
|
249
|
-
txn: algosdk_1.default.makeAssetTransferTxnWithSuggestedParamsFromObject({
|
|
250
|
-
amount: bAmt,
|
|
251
|
-
from: sender,
|
|
252
|
-
suggestedParams: params,
|
|
253
|
-
to: poolAddress,
|
|
254
|
-
assetIndex: bId
|
|
255
|
-
}),
|
|
256
|
-
signer
|
|
257
|
-
}
|
|
258
|
-
],
|
|
259
|
-
appForeignAssets: [bId, poolToken],
|
|
260
|
-
suggestedParams: Object.assign(Object.assign({}, sp), { flatFee: true, fee: 2000 }),
|
|
261
|
-
signer
|
|
262
|
-
});
|
|
263
|
-
const res = yield atc.execute(this.client, 4);
|
|
264
|
-
return res;
|
|
265
|
-
}
|
|
266
|
-
else {
|
|
267
|
-
let method;
|
|
268
|
-
if (sf1 && sf2) {
|
|
269
|
-
method = (0, utils_1.getMethodByName)(this.stableContract, 'fund');
|
|
270
|
-
}
|
|
271
|
-
else {
|
|
272
|
-
method = (0, utils_1.getMethodByName)(this.poolContract, 'fund');
|
|
273
|
-
}
|
|
274
|
-
atc.addMethodCall({
|
|
275
|
-
sender,
|
|
276
|
-
appID: poolId,
|
|
277
|
-
method,
|
|
278
|
-
methodArgs: [
|
|
279
|
-
{
|
|
280
|
-
txn: algosdk_1.default.makeAssetTransferTxnWithSuggestedParamsFromObject({
|
|
281
|
-
from: sender,
|
|
282
|
-
suggestedParams: sp,
|
|
283
|
-
to: poolAddress,
|
|
284
|
-
amount: aAmt,
|
|
285
|
-
assetIndex: aId
|
|
286
|
-
}),
|
|
287
|
-
signer
|
|
288
|
-
},
|
|
289
|
-
{
|
|
290
|
-
txn: algosdk_1.default.makeAssetTransferTxnWithSuggestedParamsFromObject({
|
|
291
|
-
amount: bAmt,
|
|
292
|
-
from: sender,
|
|
293
|
-
suggestedParams: params,
|
|
294
|
-
to: poolAddress,
|
|
295
|
-
assetIndex: bId
|
|
296
|
-
}),
|
|
297
|
-
signer
|
|
298
|
-
}
|
|
299
|
-
],
|
|
300
|
-
appForeignAssets: [aId, bId, poolToken],
|
|
301
|
-
suggestedParams: Object.assign(Object.assign({}, sp), { flatFee: true, fee: 2000 }),
|
|
302
|
-
signer
|
|
303
|
-
});
|
|
304
|
-
const res = yield atc.execute(this.client, 4);
|
|
305
|
-
return res;
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
else {
|
|
309
|
-
if (aId == 0) {
|
|
310
|
-
atc.addMethodCall({
|
|
311
|
-
sender,
|
|
312
|
-
appID: poolId,
|
|
313
|
-
method: (0, utils_1.getMethodByName)(this.poolContract, 'mint'),
|
|
314
|
-
methodArgs: [
|
|
315
|
-
{
|
|
316
|
-
txn: algosdk_1.default.makePaymentTxnWithSuggestedParamsFromObject({
|
|
317
|
-
from: sender,
|
|
318
|
-
suggestedParams: sp,
|
|
319
|
-
to: poolAddress,
|
|
320
|
-
amount: aAmt
|
|
321
|
-
}),
|
|
322
|
-
signer
|
|
323
|
-
},
|
|
324
|
-
{
|
|
325
|
-
txn: algosdk_1.default.makeAssetTransferTxnWithSuggestedParamsFromObject({
|
|
326
|
-
amount: bAmt,
|
|
327
|
-
from: sender,
|
|
328
|
-
suggestedParams: params,
|
|
329
|
-
to: poolAddress,
|
|
330
|
-
assetIndex: bId
|
|
331
|
-
}),
|
|
332
|
-
signer
|
|
333
|
-
},
|
|
334
|
-
mintAmt
|
|
335
|
-
],
|
|
336
|
-
appForeignAssets: [bId, poolToken],
|
|
337
|
-
suggestedParams: Object.assign(Object.assign({}, sp), { flatFee: true, fee: 4000 }),
|
|
338
|
-
signer
|
|
339
|
-
});
|
|
340
|
-
const res = yield atc.execute(this.client, 4);
|
|
341
|
-
return res;
|
|
342
|
-
}
|
|
343
|
-
else {
|
|
344
|
-
let method;
|
|
345
|
-
let methodArgs;
|
|
346
|
-
if (sf1 && sf2) {
|
|
347
|
-
method = (0, utils_1.getMethodByName)(this.stableContract, 'mint');
|
|
348
|
-
methodArgs = [aAmt, bAmt, mintAmt];
|
|
349
|
-
if (aAmt == 0) {
|
|
350
|
-
methodArgs.push({
|
|
351
|
-
txn: algosdk_1.default.makeAssetTransferTxnWithSuggestedParamsFromObject({
|
|
352
|
-
from: sender,
|
|
353
|
-
suggestedParams: sp,
|
|
354
|
-
to: poolAddress,
|
|
355
|
-
amount: bAmt,
|
|
356
|
-
assetIndex: bId
|
|
357
|
-
}),
|
|
358
|
-
signer
|
|
359
|
-
});
|
|
360
|
-
}
|
|
361
|
-
else if (bAmt == 0) {
|
|
362
|
-
methodArgs.push({
|
|
363
|
-
txn: algosdk_1.default.makeAssetTransferTxnWithSuggestedParamsFromObject({
|
|
364
|
-
from: sender,
|
|
365
|
-
suggestedParams: sp,
|
|
366
|
-
to: poolAddress,
|
|
367
|
-
amount: aAmt,
|
|
368
|
-
assetIndex: aId
|
|
369
|
-
}),
|
|
370
|
-
signer
|
|
371
|
-
});
|
|
372
|
-
}
|
|
373
|
-
else {
|
|
374
|
-
methodArgs.push({
|
|
375
|
-
txn: algosdk_1.default.makeAssetTransferTxnWithSuggestedParamsFromObject({
|
|
376
|
-
from: sender,
|
|
377
|
-
suggestedParams: sp,
|
|
378
|
-
to: poolAddress,
|
|
379
|
-
amount: aAmt,
|
|
380
|
-
assetIndex: aId
|
|
381
|
-
}),
|
|
382
|
-
signer
|
|
383
|
-
});
|
|
384
|
-
methodArgs.push({
|
|
385
|
-
txn: algosdk_1.default.makeAssetTransferTxnWithSuggestedParamsFromObject({
|
|
386
|
-
from: sender,
|
|
387
|
-
suggestedParams: sp,
|
|
388
|
-
to: poolAddress,
|
|
389
|
-
amount: bAmt,
|
|
390
|
-
assetIndex: bId
|
|
391
|
-
}),
|
|
392
|
-
signer
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
else {
|
|
397
|
-
method = (0, utils_1.getMethodByName)(this.poolContract, 'mint');
|
|
398
|
-
methodArgs = [
|
|
399
|
-
{
|
|
400
|
-
txn: algosdk_1.default.makeAssetTransferTxnWithSuggestedParamsFromObject({
|
|
401
|
-
from: sender,
|
|
402
|
-
suggestedParams: sp,
|
|
403
|
-
to: poolAddress,
|
|
404
|
-
amount: aAmt,
|
|
405
|
-
assetIndex: aId
|
|
406
|
-
}),
|
|
407
|
-
signer
|
|
408
|
-
},
|
|
409
|
-
{
|
|
410
|
-
txn: algosdk_1.default.makeAssetTransferTxnWithSuggestedParamsFromObject({
|
|
411
|
-
amount: bAmt,
|
|
412
|
-
from: sender,
|
|
413
|
-
suggestedParams: params,
|
|
414
|
-
to: poolAddress,
|
|
415
|
-
assetIndex: bId
|
|
416
|
-
}),
|
|
417
|
-
signer
|
|
418
|
-
},
|
|
419
|
-
mintAmt
|
|
420
|
-
];
|
|
421
|
-
}
|
|
422
|
-
atc.addMethodCall({
|
|
423
|
-
sender,
|
|
424
|
-
appID: poolId,
|
|
425
|
-
method,
|
|
426
|
-
methodArgs,
|
|
427
|
-
appForeignAssets: [aId, bId, poolToken],
|
|
428
|
-
suggestedParams: Object.assign(Object.assign({}, sp), { flatFee: true, fee: 4000 }),
|
|
429
|
-
signer
|
|
430
|
-
});
|
|
431
|
-
const res = yield atc.execute(this.client, 4);
|
|
432
|
-
return res;
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
});
|
|
436
|
-
}
|
|
437
|
-
/**
|
|
438
|
-
* remove liquidity from the pool
|
|
439
|
-
*
|
|
440
|
-
* @param sender the sender of transaction
|
|
441
|
-
* @param poolId
|
|
442
|
-
* @param poolTokenAmt
|
|
443
|
-
* @param aMinAmt
|
|
444
|
-
* @param bMinAmt
|
|
445
|
-
* @returns
|
|
446
|
-
*/
|
|
447
|
-
removeLiquidity(sender, poolId, poolTokenAmt, aMinAmt, bMinAmt, signer) {
|
|
448
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
449
|
-
const poolState = yield this.getPoolState(poolId);
|
|
450
|
-
const poolTokenId = poolState['p'];
|
|
451
|
-
const poolTokenBalance = yield this.getBalance(poolTokenId, sender);
|
|
452
|
-
if (poolTokenBalance < poolTokenAmt)
|
|
453
|
-
throw new Error('insufficient pool token balance');
|
|
454
|
-
const sp = yield this.client.getTransactionParams().do();
|
|
455
|
-
const foreignAssets = poolState['a'] == 0
|
|
456
|
-
? [poolTokenId, poolState['b']]
|
|
457
|
-
: [poolTokenId, poolState['a'], poolState['b']];
|
|
458
|
-
const sf1 = yield this.isStableAsset(poolState['a']);
|
|
459
|
-
const sf2 = yield this.isStableAsset(poolState['b']);
|
|
460
|
-
let method;
|
|
461
|
-
if (sf1 && sf2) {
|
|
462
|
-
method = (0, utils_1.getMethodByName)(this.poolContract, 'burn');
|
|
463
|
-
}
|
|
464
|
-
else {
|
|
465
|
-
method = (0, utils_1.getMethodByName)(this.stableContract, 'burn');
|
|
466
|
-
}
|
|
467
|
-
const atc = new algosdk_1.default.AtomicTransactionComposer();
|
|
468
|
-
atc.addMethodCall({
|
|
469
|
-
sender,
|
|
470
|
-
appID: poolId,
|
|
471
|
-
method,
|
|
472
|
-
methodArgs: [
|
|
473
|
-
{
|
|
474
|
-
txn: algosdk_1.default.makeAssetTransferTxnWithSuggestedParamsFromObject({
|
|
475
|
-
amount: poolTokenAmt,
|
|
476
|
-
from: sender,
|
|
477
|
-
suggestedParams: sp,
|
|
478
|
-
to: algosdk_1.default.getApplicationAddress(poolId),
|
|
479
|
-
assetIndex: poolTokenId
|
|
480
|
-
}),
|
|
481
|
-
signer
|
|
482
|
-
},
|
|
483
|
-
aMinAmt,
|
|
484
|
-
bMinAmt
|
|
485
|
-
],
|
|
486
|
-
appForeignAssets: foreignAssets,
|
|
487
|
-
suggestedParams: Object.assign(Object.assign({}, sp), { flatFee: true, fee: 4000 }),
|
|
488
|
-
signer
|
|
489
|
-
});
|
|
490
|
-
const res = yield atc.execute(this.client, 4);
|
|
491
|
-
return res;
|
|
492
|
-
});
|
|
493
|
-
}
|
|
494
|
-
/**
|
|
495
|
-
* swap tokens
|
|
496
|
-
*
|
|
497
|
-
* @param sender the sender of transaction
|
|
498
|
-
* @param inId asset id of input
|
|
499
|
-
* @param inAmt input amount
|
|
500
|
-
* @param outId asset id of output
|
|
501
|
-
* @returns
|
|
502
|
-
*/
|
|
503
|
-
swap(sender, inId, inAmt, outId, slippage, signer) {
|
|
504
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
505
|
-
let [assetIn, assetOut] = [inId, outId];
|
|
506
|
-
if (assetIn > assetOut)
|
|
507
|
-
[assetIn, assetOut] = [assetOut, assetIn];
|
|
508
|
-
const poolId = yield this.getPoolIdByAssets(assetIn, assetOut);
|
|
509
|
-
const poolAddress = algosdk_1.default.getApplicationAddress(poolId);
|
|
510
|
-
let poolState = yield this.getPoolState(poolId);
|
|
511
|
-
const poolToken = poolState['p'];
|
|
512
|
-
const outAmt = this.getSwapOutputByState(inId, outId, poolState, inAmt);
|
|
513
|
-
const minSwapAmt = (BigInt(outAmt) * (BigInt(100000) - BigInt(slippage * 1000))) /
|
|
514
|
-
BigInt(100000);
|
|
515
|
-
const params = yield this.client.getTransactionParams().do();
|
|
516
|
-
const atc = new algosdk_1.default.AtomicTransactionComposer();
|
|
517
|
-
if (!(yield this.isOptedInAsset(outId, sender))) {
|
|
518
|
-
atc.addTransaction({
|
|
519
|
-
txn: algosdk_1.default.makeAssetTransferTxnWithSuggestedParamsFromObject({
|
|
520
|
-
from: sender,
|
|
521
|
-
suggestedParams: params,
|
|
522
|
-
to: sender,
|
|
523
|
-
amount: 0,
|
|
524
|
-
assetIndex: outId
|
|
525
|
-
}),
|
|
526
|
-
signer
|
|
527
|
-
});
|
|
528
|
-
}
|
|
529
|
-
if (inId == 0) {
|
|
530
|
-
let foreignAssets = [outId, poolToken];
|
|
531
|
-
atc.addMethodCall({
|
|
532
|
-
sender,
|
|
533
|
-
appID: poolId,
|
|
534
|
-
method: (0, utils_1.getMethodByName)(this.poolContract, 'swap'),
|
|
535
|
-
methodArgs: [
|
|
536
|
-
{
|
|
537
|
-
txn: algosdk_1.default.makePaymentTxnWithSuggestedParamsFromObject({
|
|
538
|
-
from: sender,
|
|
539
|
-
suggestedParams: params,
|
|
540
|
-
to: poolAddress,
|
|
541
|
-
amount: inAmt
|
|
542
|
-
}),
|
|
543
|
-
signer
|
|
544
|
-
},
|
|
545
|
-
minSwapAmt
|
|
546
|
-
],
|
|
547
|
-
appForeignAssets: foreignAssets,
|
|
548
|
-
suggestedParams: Object.assign(Object.assign({}, params), { flatFee: true, fee: 2000 }),
|
|
549
|
-
signer
|
|
550
|
-
});
|
|
551
|
-
const res = yield atc.execute(this.client, 4);
|
|
552
|
-
return res;
|
|
553
|
-
}
|
|
554
|
-
else {
|
|
555
|
-
let foreignAssets;
|
|
556
|
-
if (inId < outId) {
|
|
557
|
-
foreignAssets = [inId, outId, poolToken];
|
|
558
|
-
}
|
|
559
|
-
else {
|
|
560
|
-
foreignAssets = [outId, inId, poolToken];
|
|
561
|
-
}
|
|
562
|
-
atc.addMethodCall({
|
|
563
|
-
sender,
|
|
564
|
-
appID: poolId,
|
|
565
|
-
method: (0, utils_1.getMethodByName)(this.poolContract, 'swap'),
|
|
566
|
-
methodArgs: [
|
|
567
|
-
{
|
|
568
|
-
txn: algosdk_1.default.makeAssetTransferTxnWithSuggestedParamsFromObject({
|
|
569
|
-
from: sender,
|
|
570
|
-
suggestedParams: params,
|
|
571
|
-
to: poolAddress,
|
|
572
|
-
amount: inAmt,
|
|
573
|
-
assetIndex: inId
|
|
574
|
-
}),
|
|
575
|
-
signer
|
|
576
|
-
},
|
|
577
|
-
minSwapAmt
|
|
578
|
-
],
|
|
579
|
-
appForeignAssets: foreignAssets,
|
|
580
|
-
suggestedParams: Object.assign(Object.assign({}, params), { flatFee: true, fee: 2000 }),
|
|
581
|
-
signer
|
|
582
|
-
});
|
|
583
|
-
const res = yield atc.execute(this.client, 4);
|
|
584
|
-
return res;
|
|
585
|
-
}
|
|
586
|
-
});
|
|
587
|
-
}
|
|
588
|
-
/**
|
|
589
|
-
* get LP token by asset A and B
|
|
590
|
-
*
|
|
591
|
-
* @param assetA
|
|
592
|
-
* @param assetB
|
|
593
|
-
* @returns
|
|
594
|
-
*/
|
|
595
|
-
getPoolToken(assetA, assetB) {
|
|
596
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
597
|
-
const poolId = yield this.getPoolIdByAssets(assetA, assetB);
|
|
598
|
-
const state = yield this.getPoolState(poolId);
|
|
599
|
-
if (state['a'] != assetA || state['b'] != assetB) {
|
|
600
|
-
throw new Error('incorrect pair');
|
|
601
|
-
}
|
|
602
|
-
return state['p'];
|
|
603
|
-
});
|
|
604
|
-
}
|
|
605
|
-
/**
|
|
606
|
-
* get pool app id by asset A and B
|
|
607
|
-
*
|
|
608
|
-
* @param assetA
|
|
609
|
-
* @param assetB
|
|
610
|
-
* @returns
|
|
611
|
-
*/
|
|
612
|
-
getPoolIdByAssets(assetA, assetB) {
|
|
613
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
614
|
-
if (assetA > assetB)
|
|
615
|
-
[assetA, assetB] = [assetB, assetA];
|
|
616
|
-
const cachedId = String(assetA) + String(assetB);
|
|
617
|
-
if (this.poolsCache[cachedId])
|
|
618
|
-
return this.poolsCache[cachedId].poolId;
|
|
619
|
-
else {
|
|
620
|
-
const boxName = new Uint8Array([
|
|
621
|
-
...algosdk_1.default.encodeUint64(assetA),
|
|
622
|
-
...algosdk_1.default.encodeUint64(assetB)
|
|
623
|
-
]);
|
|
624
|
-
const box = yield this.client
|
|
625
|
-
.getApplicationBoxByName(this.appId, boxName)
|
|
626
|
-
.do();
|
|
627
|
-
const poolId = algosdk_1.default.decodeUint64(box.value, 'safe');
|
|
628
|
-
return poolId;
|
|
629
|
-
}
|
|
630
|
-
});
|
|
631
|
-
}
|
|
632
|
-
/**
|
|
633
|
-
* get pool app id by LP token
|
|
634
|
-
* @param tokenId
|
|
635
|
-
* @returns
|
|
636
|
-
*/
|
|
637
|
-
getPoolByToken(tokenId) {
|
|
638
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
639
|
-
const pair = Object.values(this.poolsCache).find((pair) => pair.poolState['p'] == tokenId);
|
|
640
|
-
if (pair)
|
|
641
|
-
return pair;
|
|
642
|
-
else {
|
|
643
|
-
const pairs = yield this.getPairs();
|
|
644
|
-
const idx = pairs.findIndex((pair) => pair.poolState['p'] == tokenId);
|
|
645
|
-
if (idx == -1)
|
|
646
|
-
throw new Error('non-exist pool');
|
|
647
|
-
const correctPair = pairs[idx];
|
|
648
|
-
return correctPair;
|
|
649
|
-
}
|
|
650
|
-
});
|
|
651
|
-
}
|
|
652
|
-
/**
|
|
653
|
-
* Get pool by asset A id and asset B id
|
|
654
|
-
* @param assetA
|
|
655
|
-
* @param assetB
|
|
656
|
-
* @returns
|
|
657
|
-
*/
|
|
658
|
-
getPoolByAssets(assetA, assetB) {
|
|
659
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
660
|
-
if (assetA > assetB)
|
|
661
|
-
[assetA, assetB] = [assetB, assetA];
|
|
662
|
-
const cachedId = String(assetA) + String(assetB);
|
|
663
|
-
if (this.poolsCache[cachedId]) {
|
|
664
|
-
const poolState = yield this.getPoolState(this.poolsCache[cachedId].poolId);
|
|
665
|
-
return Object.assign(Object.assign({}, this.poolsCache[cachedId]), { poolState });
|
|
666
|
-
}
|
|
667
|
-
else {
|
|
668
|
-
const boxName = new Uint8Array([
|
|
669
|
-
...algosdk_1.default.encodeUint64(assetA),
|
|
670
|
-
...algosdk_1.default.encodeUint64(assetB)
|
|
671
|
-
]);
|
|
672
|
-
const box = yield this.client
|
|
673
|
-
.getApplicationBoxByName(this.appId, boxName)
|
|
674
|
-
.do();
|
|
675
|
-
const poolId = algosdk_1.default.decodeUint64(box.value, 'safe');
|
|
676
|
-
const poolState = yield this.getPoolState(poolId);
|
|
677
|
-
const poolToken = poolState['p'];
|
|
678
|
-
let aa;
|
|
679
|
-
if (assetA == 0) {
|
|
680
|
-
aa = {
|
|
681
|
-
params: {
|
|
682
|
-
name: constants_1.ALGO.name,
|
|
683
|
-
decimals: constants_1.ALGO.decimals,
|
|
684
|
-
'unit-name': constants_1.ALGO.unitName
|
|
685
|
-
}
|
|
686
|
-
};
|
|
687
|
-
}
|
|
688
|
-
else {
|
|
689
|
-
aa = yield this.getAsset(assetA);
|
|
690
|
-
}
|
|
691
|
-
const bb = yield this.getAsset(assetB);
|
|
692
|
-
const pair = {
|
|
693
|
-
aId: assetA,
|
|
694
|
-
aName: aa.params['name'],
|
|
695
|
-
aDecimals: aa.params['decimals'],
|
|
696
|
-
aUnitName: aa.params['unit-name'],
|
|
697
|
-
bId: assetB,
|
|
698
|
-
bName: bb.params['name'],
|
|
699
|
-
bDecimals: bb.params['decimals'],
|
|
700
|
-
bUnitName: bb.params['unit-name'],
|
|
701
|
-
poolId,
|
|
702
|
-
poolToken,
|
|
703
|
-
poolState,
|
|
704
|
-
type: poolState['pt'] || 'CONSTANT_PRODUCT',
|
|
705
|
-
fee: poolState['f'] || 20
|
|
706
|
-
};
|
|
707
|
-
this.poolsCache[cachedId] = pair;
|
|
708
|
-
return pair;
|
|
709
|
-
}
|
|
710
|
-
});
|
|
711
|
-
}
|
|
712
|
-
/**
|
|
713
|
-
* get all pools
|
|
714
|
-
*
|
|
715
|
-
* @returns
|
|
716
|
-
*/
|
|
717
|
-
getPairs() {
|
|
718
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
719
|
-
const appAddress = algosdk_1.default.getApplicationAddress(this.appId);
|
|
720
|
-
const appInfo = yield this.client.accountInformation(appAddress).do();
|
|
721
|
-
const createdApps = appInfo['created-apps'];
|
|
722
|
-
let pools = [];
|
|
723
|
-
for (const app of createdApps) {
|
|
724
|
-
const poolId = app['id'];
|
|
725
|
-
const stateArray = app['params']['global-state'];
|
|
726
|
-
const poolState = (0, utils_1.decodeStateArray)(stateArray);
|
|
727
|
-
const aId = poolState['a'];
|
|
728
|
-
const bId = poolState['b'];
|
|
729
|
-
const poolToken = poolState['p'];
|
|
730
|
-
const type = poolState['pt'] || 'CONSTANT_PRODUCT';
|
|
731
|
-
const fee = poolState['f'] || 20;
|
|
732
|
-
const cachedId = String(aId) + String(bId);
|
|
733
|
-
const cachedPool = this.poolsCache[cachedId];
|
|
734
|
-
if (cachedPool) {
|
|
735
|
-
pools.push(Object.assign(Object.assign({}, cachedPool), { poolToken, poolId, poolState }));
|
|
736
|
-
}
|
|
737
|
-
else {
|
|
738
|
-
let assetA;
|
|
739
|
-
if (aId == 0) {
|
|
740
|
-
assetA = {
|
|
741
|
-
params: {
|
|
742
|
-
decimals: constants_1.ALGO.decimals,
|
|
743
|
-
name: constants_1.ALGO.name,
|
|
744
|
-
'unit-name': constants_1.ALGO.unitName
|
|
745
|
-
}
|
|
746
|
-
};
|
|
747
|
-
}
|
|
748
|
-
else {
|
|
749
|
-
assetA = yield this.getAsset(aId);
|
|
750
|
-
}
|
|
751
|
-
const assetB = yield this.getAsset(bId);
|
|
752
|
-
const pool = {
|
|
753
|
-
aId,
|
|
754
|
-
aDecimals: assetA.params['decimals'],
|
|
755
|
-
aName: assetA.params['name'],
|
|
756
|
-
aUnitName: assetA.params['unit-name'],
|
|
757
|
-
bId,
|
|
758
|
-
bDecimals: assetB.params['decimals'],
|
|
759
|
-
bName: assetB.params['name'],
|
|
760
|
-
bUnitName: assetB.params['unit-name'],
|
|
761
|
-
poolToken,
|
|
762
|
-
poolId,
|
|
763
|
-
poolState,
|
|
764
|
-
fee,
|
|
765
|
-
type: type
|
|
766
|
-
};
|
|
767
|
-
pools.push(pool);
|
|
768
|
-
this.poolsCache[cachedId] = pool;
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
return pools;
|
|
772
|
-
});
|
|
773
|
-
}
|
|
774
|
-
/**
|
|
775
|
-
* get balances of an address
|
|
776
|
-
*
|
|
777
|
-
* @param address
|
|
778
|
-
* @returns
|
|
779
|
-
*/
|
|
780
|
-
getBalances(address) {
|
|
781
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
782
|
-
const accountInfo = yield this.client.accountInformation(address).do();
|
|
783
|
-
const balances = {
|
|
784
|
-
'0': accountInfo['amount']
|
|
785
|
-
};
|
|
786
|
-
const assets = accountInfo['assets'];
|
|
787
|
-
for (let i = 0; i < assets.length; i++) {
|
|
788
|
-
const assetId = assets[i]['asset-id'];
|
|
789
|
-
const assetAmt = assets[i]['amount'];
|
|
790
|
-
balances[assetId] = assetAmt;
|
|
791
|
-
}
|
|
792
|
-
return balances;
|
|
793
|
-
});
|
|
794
|
-
}
|
|
795
|
-
/**
|
|
796
|
-
* get balance of an address per asset
|
|
797
|
-
*
|
|
798
|
-
* @param assetId
|
|
799
|
-
* @param address
|
|
800
|
-
* @returns
|
|
801
|
-
*/
|
|
802
|
-
getBalance(assetId, address) {
|
|
803
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
804
|
-
const balances = yield this.getBalances(address);
|
|
805
|
-
return balances[assetId.toString()];
|
|
806
|
-
});
|
|
807
|
-
}
|
|
808
|
-
/**
|
|
809
|
-
* check if an address opted in an asset
|
|
810
|
-
*
|
|
811
|
-
* @param assetId
|
|
812
|
-
* @param addr
|
|
813
|
-
* @returns
|
|
814
|
-
*/
|
|
815
|
-
isOptedInAsset(assetId, addr) {
|
|
816
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
817
|
-
const balances = yield this.getBalances(addr);
|
|
818
|
-
return Object.keys(balances).includes(assetId.toString());
|
|
819
|
-
});
|
|
820
|
-
}
|
|
821
|
-
/**
|
|
822
|
-
* get assets of addr
|
|
823
|
-
*
|
|
824
|
-
* @param addr
|
|
825
|
-
* @returns
|
|
826
|
-
*/
|
|
827
|
-
getAssetList(addr) {
|
|
828
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
829
|
-
const accountInfo = yield this.client.accountInformation(addr).do();
|
|
830
|
-
const as = accountInfo['assets'];
|
|
831
|
-
const assetList = [];
|
|
832
|
-
for (let i = 0; i < as.length; i++) {
|
|
833
|
-
const a = as[i];
|
|
834
|
-
try {
|
|
835
|
-
const b = yield this.client.getAssetByID(a['asset-id']).do();
|
|
836
|
-
assetList.push({
|
|
837
|
-
id: b['index'],
|
|
838
|
-
name: b['params']['unit-name']
|
|
839
|
-
});
|
|
840
|
-
}
|
|
841
|
-
catch (e) {
|
|
842
|
-
console.log(e);
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
return assetList;
|
|
846
|
-
});
|
|
847
|
-
}
|
|
848
|
-
/**
|
|
849
|
-
* get output amount when a user swap A to B
|
|
850
|
-
*
|
|
851
|
-
* @param assetIn id of input asset
|
|
852
|
-
* @param assetOut id of output asset
|
|
853
|
-
* @param state pool state
|
|
854
|
-
* @param amtIn input amount
|
|
855
|
-
* @returns
|
|
856
|
-
*/
|
|
857
|
-
getSwapOutputByState(assetIn, assetOut, state, amtIn) {
|
|
858
|
-
const aSup = state['ra'];
|
|
859
|
-
const bSup = state['rb'];
|
|
860
|
-
let [inSup, outSup] = [aSup, bSup];
|
|
861
|
-
if (assetIn > assetOut)
|
|
862
|
-
[inSup, outSup] = [bSup, aSup];
|
|
863
|
-
const amtOut = (BigInt(amtIn) * BigInt(1000 - 3) * BigInt(outSup)) /
|
|
864
|
-
(BigInt(inSup) * BigInt(1000) + BigInt(amtIn) * BigInt(1000 - 3));
|
|
865
|
-
return amtOut;
|
|
866
|
-
}
|
|
867
|
-
/**
|
|
868
|
-
* get output amount after swap
|
|
869
|
-
*
|
|
870
|
-
* @param txId transaction id
|
|
871
|
-
* @returns
|
|
872
|
-
*/
|
|
873
|
-
getAmountAfterSwap(txId) {
|
|
874
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
875
|
-
const txnInfo = yield this.client
|
|
876
|
-
.pendingTransactionInformation(txId)
|
|
877
|
-
.do();
|
|
878
|
-
const res = new PendingTxnResponse(txnInfo);
|
|
879
|
-
if (res.logs.length) {
|
|
880
|
-
return algosdk_1.default.decodeUint64(res.logs[0], 'safe');
|
|
881
|
-
}
|
|
882
|
-
else {
|
|
883
|
-
throw new Error('no swap transaction');
|
|
884
|
-
}
|
|
885
|
-
});
|
|
886
|
-
}
|
|
887
|
-
/**
|
|
888
|
-
* Get liquidity token amounts
|
|
889
|
-
*
|
|
890
|
-
* @param assetA id of asset A to send the A-B pool
|
|
891
|
-
* @param assetAAmt amount of asset A
|
|
892
|
-
* @param assetB id of asset B
|
|
893
|
-
* @param assetBAmt amount of asset B to send the A-B pool
|
|
894
|
-
* @returns int
|
|
895
|
-
*/
|
|
896
|
-
getMintAmt(assetA, assetAAmt, assetB, assetBAmt) {
|
|
897
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
898
|
-
if (assetA > assetB) {
|
|
899
|
-
[assetA, assetB] = [assetB, assetA];
|
|
900
|
-
[assetAAmt, assetBAmt] = [assetBAmt, assetAAmt];
|
|
901
|
-
}
|
|
902
|
-
const poolId = yield this.getPoolIdByAssets(assetA, assetB);
|
|
903
|
-
const state = yield this.getPoolState(poolId);
|
|
904
|
-
if (state['a'] != assetA || state['b'] != assetB) {
|
|
905
|
-
throw new Error('incorrect pair');
|
|
906
|
-
}
|
|
907
|
-
const reserveA = BigInt(state['ra']);
|
|
908
|
-
const reserveB = BigInt(state['rb']);
|
|
909
|
-
const issued = BigInt(state['ma']);
|
|
910
|
-
if (reserveA == BigInt(0) && reserveB == BigInt(0)) {
|
|
911
|
-
// on_fund
|
|
912
|
-
const scale = BigInt(1000);
|
|
913
|
-
return (0, utils_1.sqrt)(BigInt(assetAAmt) * BigInt(assetBAmt)) - scale;
|
|
914
|
-
}
|
|
915
|
-
else {
|
|
916
|
-
// on_mint
|
|
917
|
-
if (BigInt(assetAAmt) * reserveB < BigInt(assetBAmt) * reserveA) {
|
|
918
|
-
return (BigInt(assetAAmt) * issued) / reserveA;
|
|
919
|
-
}
|
|
920
|
-
else {
|
|
921
|
-
return (BigInt(assetBAmt) * issued) / reserveB;
|
|
922
|
-
}
|
|
923
|
-
}
|
|
924
|
-
});
|
|
925
|
-
}
|
|
926
|
-
/**
|
|
927
|
-
* Get liquidity token amounts by pool state
|
|
928
|
-
*
|
|
929
|
-
* @param state pool state
|
|
930
|
-
* @param assetAAmt amount of asset A
|
|
931
|
-
* @param assetBAmt amount of asset B to send the A-B pool
|
|
932
|
-
* @returns int
|
|
933
|
-
*/
|
|
934
|
-
getMintAmtByState(state, assetAAmt, assetBAmt) {
|
|
935
|
-
const reserveA = BigInt(state['ra']);
|
|
936
|
-
const reserveB = BigInt(state['rb']);
|
|
937
|
-
const issued = BigInt(state['ma']);
|
|
938
|
-
if (reserveA == BigInt(0) && reserveB == BigInt(0)) {
|
|
939
|
-
// on_fund
|
|
940
|
-
const scale = BigInt(1000);
|
|
941
|
-
return (0, utils_1.sqrt)(BigInt(assetAAmt) * BigInt(assetBAmt)) - scale;
|
|
942
|
-
}
|
|
943
|
-
else {
|
|
944
|
-
// on_mint
|
|
945
|
-
if (BigInt(assetAAmt) * reserveB < BigInt(assetBAmt) * reserveA) {
|
|
946
|
-
return (BigInt(assetAAmt) * issued) / reserveA;
|
|
947
|
-
}
|
|
948
|
-
else {
|
|
949
|
-
return (BigInt(assetBAmt) * issued) / reserveB;
|
|
950
|
-
}
|
|
951
|
-
}
|
|
952
|
-
}
|
|
953
|
-
/**
|
|
954
|
-
* Make opt-in for asset/pool
|
|
955
|
-
*
|
|
956
|
-
* @param sender the sender of transaction
|
|
957
|
-
* @param assetId id of asset/pool
|
|
958
|
-
* @param signer transaction signer
|
|
959
|
-
* @returns
|
|
960
|
-
*/
|
|
961
|
-
prepareOptInTxn(sender, assetId, signer) {
|
|
962
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
963
|
-
const params = yield this.client.getTransactionParams().do();
|
|
964
|
-
const atc = new algosdk_1.default.AtomicTransactionComposer();
|
|
965
|
-
atc.addTransaction({
|
|
966
|
-
txn: algosdk_1.default.makeAssetTransferTxnWithSuggestedParamsFromObject({
|
|
967
|
-
amount: 0,
|
|
968
|
-
from: sender,
|
|
969
|
-
suggestedParams: params,
|
|
970
|
-
to: sender,
|
|
971
|
-
assetIndex: assetId
|
|
972
|
-
}),
|
|
973
|
-
signer
|
|
974
|
-
});
|
|
975
|
-
const res = yield atc.execute(this.client, 4);
|
|
976
|
-
return res;
|
|
977
|
-
});
|
|
978
|
-
}
|
|
979
|
-
/**
|
|
980
|
-
* Get assets amounts after pool token burn
|
|
981
|
-
*
|
|
982
|
-
* @param assetA id of asset A
|
|
983
|
-
* @param assetB id of asset B
|
|
984
|
-
* @param burnAmt burn amount
|
|
985
|
-
* @returns
|
|
986
|
-
*/
|
|
987
|
-
getAssetAmtAfterBurnLP(assetA, assetB, burnAmt) {
|
|
988
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
989
|
-
const poolId = yield this.getPoolIdByAssets(assetA, assetB);
|
|
990
|
-
const state = yield this.getPoolState(poolId);
|
|
991
|
-
if (state['a'] != assetA || state['b'] != assetB) {
|
|
992
|
-
throw new Error('incorrect pair');
|
|
993
|
-
}
|
|
994
|
-
const issued = BigInt(state['ma']);
|
|
995
|
-
const reserveA = BigInt(state['ra']);
|
|
996
|
-
const reserveB = BigInt(state['rb']);
|
|
997
|
-
const aBurnedAmt = (BigInt(reserveA) * BigInt(burnAmt)) / issued;
|
|
998
|
-
const bBurnedAmt = (BigInt(reserveB) * BigInt(burnAmt)) / issued;
|
|
999
|
-
return {
|
|
1000
|
-
assetA: aBurnedAmt,
|
|
1001
|
-
assetB: bBurnedAmt
|
|
1002
|
-
};
|
|
1003
|
-
});
|
|
1004
|
-
}
|
|
1005
|
-
/**
|
|
1006
|
-
* Get assets amounts after pool token burn by state
|
|
1007
|
-
*
|
|
1008
|
-
* @param state pool state
|
|
1009
|
-
* @param burnAmt burn amount
|
|
1010
|
-
* @returns
|
|
1011
|
-
*/
|
|
1012
|
-
getAssetAmtAfterBurnLPByState(state, burnAmt) {
|
|
1013
|
-
const issued = BigInt(state['ma']);
|
|
1014
|
-
const reserveA = BigInt(state['ra']);
|
|
1015
|
-
const reserveB = BigInt(state['rb']);
|
|
1016
|
-
const aBurnedAmt = (BigInt(reserveA) * BigInt(burnAmt)) / issued;
|
|
1017
|
-
const bBurnedAmt = (BigInt(reserveB) * BigInt(burnAmt)) / issued;
|
|
1018
|
-
return {
|
|
1019
|
-
assetA: aBurnedAmt,
|
|
1020
|
-
assetB: bBurnedAmt
|
|
1021
|
-
};
|
|
1022
|
-
}
|
|
1023
|
-
/**
|
|
1024
|
-
* get input amount from output when a user swap A to B
|
|
1025
|
-
*
|
|
1026
|
-
* @param assetIn id of input asset
|
|
1027
|
-
* @param assetOut id of output asset
|
|
1028
|
-
* @param amtOut output amount
|
|
1029
|
-
* @returns
|
|
1030
|
-
*/
|
|
1031
|
-
getSwapInput(assetIn, assetOut, amtOut) {
|
|
1032
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1033
|
-
let [assetA, assetB] = [assetIn, assetOut];
|
|
1034
|
-
if (assetIn > assetOut)
|
|
1035
|
-
[assetA, assetB] = [assetOut, assetIn];
|
|
1036
|
-
const poolId = yield this.getPoolIdByAssets(assetA, assetB);
|
|
1037
|
-
const state = yield this.getPoolState(poolId);
|
|
1038
|
-
if (state['a'] != assetA || state['b'] != assetB) {
|
|
1039
|
-
throw new Error('incorrect pair');
|
|
1040
|
-
}
|
|
1041
|
-
const aSup = state['ra'];
|
|
1042
|
-
const bSup = state['rb'];
|
|
1043
|
-
let [inSup, outSup] = [aSup, bSup];
|
|
1044
|
-
if (assetIn > assetOut)
|
|
1045
|
-
[inSup, outSup] = [bSup, aSup];
|
|
1046
|
-
const amtIn = (BigInt(amtOut) * BigInt(inSup) * BigInt(1000)) /
|
|
1047
|
-
(BigInt(1000 - 3) * (BigInt(outSup) - BigInt(amtOut))) +
|
|
1048
|
-
BigInt(1);
|
|
1049
|
-
return amtIn;
|
|
1050
|
-
});
|
|
1051
|
-
}
|
|
1052
|
-
/**
|
|
1053
|
-
* get input amount from output when a user swap A to B
|
|
1054
|
-
*
|
|
1055
|
-
* @param assetIn id of input asset
|
|
1056
|
-
* @param assetOut id of output asset
|
|
1057
|
-
* @param amtOut output amount
|
|
1058
|
-
* @param state pool state
|
|
1059
|
-
* @returns
|
|
1060
|
-
*/
|
|
1061
|
-
getSwapInputByState(assetIn, assetOut, state, amtOut) {
|
|
1062
|
-
const aSup = state['ra'];
|
|
1063
|
-
const bSup = state['rb'];
|
|
1064
|
-
let [inSup, outSup] = [aSup, bSup];
|
|
1065
|
-
if (assetIn > assetOut)
|
|
1066
|
-
[inSup, outSup] = [bSup, aSup];
|
|
1067
|
-
const amtIn = (BigInt(amtOut) * BigInt(inSup) * BigInt(1000)) /
|
|
1068
|
-
(BigInt(1000 - 3) * (BigInt(outSup) - BigInt(amtOut))) +
|
|
1069
|
-
BigInt(1);
|
|
1070
|
-
return amtIn;
|
|
1071
|
-
}
|
|
1072
|
-
/**
|
|
1073
|
-
* get pool ratio
|
|
1074
|
-
* @param assetIn id of asset A
|
|
1075
|
-
* @param assetOut id of asset B
|
|
1076
|
-
* @returns
|
|
1077
|
-
*/
|
|
1078
|
-
getPoolRatio(assetIn, assetOut) {
|
|
1079
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1080
|
-
let [assetA, assetB] = [assetIn, assetOut];
|
|
1081
|
-
if (assetIn.index > assetOut.index)
|
|
1082
|
-
[assetA, assetB] = [assetOut, assetIn];
|
|
1083
|
-
const poolId = yield this.getPoolIdByAssets(assetA.index, assetB.index);
|
|
1084
|
-
const state = yield this.getPoolState(poolId);
|
|
1085
|
-
if (state['a'] != assetA.index || state['b'] != assetB.index) {
|
|
1086
|
-
throw new Error('incorrect pair');
|
|
1087
|
-
}
|
|
1088
|
-
if (state['ra'] == 0 || state['rb'] == 0)
|
|
1089
|
-
return 0;
|
|
1090
|
-
const aSup = { amount: BigInt(state['ra']), decimals: assetA.decimals };
|
|
1091
|
-
const bSup = { amount: BigInt(state['rb']), decimals: assetB.decimals };
|
|
1092
|
-
let [inSup, outSup] = [aSup, bSup];
|
|
1093
|
-
if (assetIn.index > assetOut.index)
|
|
1094
|
-
[inSup, outSup] = [bSup, aSup];
|
|
1095
|
-
const ratio = Number(inSup.amount) /
|
|
1096
|
-
Math.pow(10, inSup.decimals) /
|
|
1097
|
-
(Number(outSup.amount) / Math.pow(10, outSup.decimals));
|
|
1098
|
-
return ratio;
|
|
1099
|
-
});
|
|
1100
|
-
}
|
|
1101
|
-
/**
|
|
1102
|
-
* get pool ratio
|
|
1103
|
-
* @param state pool state
|
|
1104
|
-
* @param aDecimals decimals of asset A
|
|
1105
|
-
* @param bDecimals decimals of asset B
|
|
1106
|
-
* @returns
|
|
1107
|
-
*/
|
|
1108
|
-
getPoolRatioByState(state, aDecimals, bDecimals) {
|
|
1109
|
-
if (state['ra'] == 0 || state['rb'] == 0)
|
|
1110
|
-
return 0;
|
|
1111
|
-
const aSup = { amount: BigInt(state['ra']), decimals: aDecimals };
|
|
1112
|
-
const bSup = { amount: BigInt(state['rb']), decimals: bDecimals };
|
|
1113
|
-
const ratio = Number(aSup.amount) /
|
|
1114
|
-
Math.pow(10, aSup.decimals) /
|
|
1115
|
-
(Number(bSup.amount) / Math.pow(10, bSup.decimals));
|
|
1116
|
-
return ratio;
|
|
1117
|
-
}
|
|
1118
|
-
/**
|
|
1119
|
-
* Get pool state
|
|
1120
|
-
* @param poolId id of pool
|
|
1121
|
-
* @returns
|
|
1122
|
-
*/
|
|
1123
|
-
getPoolState(poolId) {
|
|
1124
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1125
|
-
const appInfo = yield this.client.getApplicationByID(poolId).do();
|
|
1126
|
-
const stateArray = appInfo['params']['global-state'];
|
|
1127
|
-
const state = (0, utils_1.decodeStateArray)(stateArray);
|
|
1128
|
-
return state;
|
|
1129
|
-
});
|
|
1130
|
-
}
|
|
1131
|
-
/**
|
|
1132
|
-
* Get all pool states
|
|
1133
|
-
* @returns
|
|
1134
|
-
*/
|
|
1135
|
-
getPoolStates() {
|
|
1136
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1137
|
-
const appAddress = algosdk_1.default.getApplicationAddress(this.appId);
|
|
1138
|
-
const appInfo = yield this.client.accountInformation(appAddress).do();
|
|
1139
|
-
const createdApps = appInfo['created-apps'];
|
|
1140
|
-
const states = {};
|
|
1141
|
-
createdApps.forEach((app) => {
|
|
1142
|
-
const id = app['id'];
|
|
1143
|
-
const stateArray = app['params']['global-state'];
|
|
1144
|
-
const state = (0, utils_1.decodeStateArray)(stateArray);
|
|
1145
|
-
states[id] = state;
|
|
1146
|
-
});
|
|
1147
|
-
return states;
|
|
1148
|
-
});
|
|
1149
|
-
}
|
|
1150
|
-
/**
|
|
1151
|
-
* get price impact when a user swaps A to B
|
|
1152
|
-
* @param assetA id of asset A
|
|
1153
|
-
* @param assetB id of asset B
|
|
1154
|
-
* @param inAmt input amout
|
|
1155
|
-
* @returns
|
|
1156
|
-
*/
|
|
1157
|
-
getPriceImpact(assetA, assetB, inAmt) {
|
|
1158
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1159
|
-
const poolId = yield this.getPoolIdByAssets(assetA, assetB);
|
|
1160
|
-
const state = yield this.getPoolState(poolId);
|
|
1161
|
-
let [inId, outId] = [assetA, assetB];
|
|
1162
|
-
if (assetA > assetB)
|
|
1163
|
-
[inId, outId] = [assetB, assetA];
|
|
1164
|
-
if (state['a'] != inId || state['b'] != outId) {
|
|
1165
|
-
throw new Error('incorrect pair');
|
|
1166
|
-
}
|
|
1167
|
-
const aSup = state['ra'];
|
|
1168
|
-
const bSup = state['rb'];
|
|
1169
|
-
let [inSup, outSup] = [aSup, bSup];
|
|
1170
|
-
if (assetA > assetB)
|
|
1171
|
-
[inSup, outSup] = [outSup, inSup];
|
|
1172
|
-
const pb = inSup / outSup;
|
|
1173
|
-
const pa = (inSup + inAmt) / ((inSup * outSup) / (inSup + inAmt));
|
|
1174
|
-
return (pa - pb) / pb;
|
|
1175
|
-
});
|
|
1176
|
-
}
|
|
1177
|
-
/**
|
|
1178
|
-
* get price impact when a user swaps A to B by state
|
|
1179
|
-
* @param poolState pool state
|
|
1180
|
-
* @param assetA id of asset A
|
|
1181
|
-
* @param assetB id of asset B
|
|
1182
|
-
* @param inAmt input amout
|
|
1183
|
-
* @returns
|
|
1184
|
-
*/
|
|
1185
|
-
getPriceImpactByState(poolState, inId, outId, inAmt) {
|
|
1186
|
-
const aSup = poolState['ra'];
|
|
1187
|
-
const bSup = poolState['rb'];
|
|
1188
|
-
let [inSup, outSup] = [aSup, bSup];
|
|
1189
|
-
if (inId > outId)
|
|
1190
|
-
[inSup, outSup] = [bSup, aSup];
|
|
1191
|
-
const pb = inSup / outSup;
|
|
1192
|
-
const pa = (inSup + inAmt) / ((inSup * outSup) / (inSup + inAmt));
|
|
1193
|
-
return (pa - pb) / pb;
|
|
1194
|
-
}
|
|
1195
|
-
/**
|
|
1196
|
-
* get price impact and swap amount when a user swaps A to B
|
|
1197
|
-
* @param assetA id of asset A
|
|
1198
|
-
* @param assetB id of asset B
|
|
1199
|
-
* @param inAmt input amout
|
|
1200
|
-
* @returns
|
|
1201
|
-
*/
|
|
1202
|
-
getSwapResults(inId, outId, amount) {
|
|
1203
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1204
|
-
let [assetA, assetB] = [inId, outId];
|
|
1205
|
-
if (inId > outId)
|
|
1206
|
-
[assetA, assetB] = [outId, inId];
|
|
1207
|
-
const poolId = yield this.getPoolIdByAssets(assetA, assetB);
|
|
1208
|
-
const state = yield this.getPoolState(poolId);
|
|
1209
|
-
if (state['a'] != assetA || state['b'] != assetB) {
|
|
1210
|
-
throw new Error('incorrect pair');
|
|
1211
|
-
}
|
|
1212
|
-
const aSup = state['ra'];
|
|
1213
|
-
const bSup = state['rb'];
|
|
1214
|
-
let [inSup, outSup] = [aSup, bSup];
|
|
1215
|
-
if (inId > outId)
|
|
1216
|
-
[inSup, outSup] = [bSup, aSup];
|
|
1217
|
-
const swapOutput = (BigInt(amount) * BigInt(1000 - 3) * BigInt(outSup)) /
|
|
1218
|
-
(BigInt(inSup * 1000) + BigInt(amount) * BigInt(1000 - 3));
|
|
1219
|
-
const swapInput = (BigInt(amount) * BigInt(inSup) * BigInt(1000)) /
|
|
1220
|
-
(BigInt(1000 - 3) * (BigInt(outSup) - BigInt(amount)));
|
|
1221
|
-
return {
|
|
1222
|
-
swapOutput,
|
|
1223
|
-
swapInput
|
|
1224
|
-
};
|
|
1225
|
-
});
|
|
1226
|
-
}
|
|
1227
|
-
getSwapResultsByState(inId, outId, state, amount) {
|
|
1228
|
-
let [assetA, assetB] = [inId, outId];
|
|
1229
|
-
if (inId > outId)
|
|
1230
|
-
[assetA, assetB] = [outId, inId];
|
|
1231
|
-
if (state['a'] != assetA || state['b'] != assetB) {
|
|
1232
|
-
throw new Error('incorrect pair');
|
|
1233
|
-
}
|
|
1234
|
-
const aSup = state['ra'];
|
|
1235
|
-
const bSup = state['rb'];
|
|
1236
|
-
let [inSup, outSup] = [aSup, bSup];
|
|
1237
|
-
if (inId > outId)
|
|
1238
|
-
[inSup, outSup] = [bSup, aSup];
|
|
1239
|
-
const swapOutput = (BigInt(amount) * BigInt(1000 - 3) * BigInt(outSup)) /
|
|
1240
|
-
(BigInt(inSup * 1000) + BigInt(amount) * BigInt(1000 - 3));
|
|
1241
|
-
const swapInput = (BigInt(amount) * BigInt(inSup) * BigInt(1000)) /
|
|
1242
|
-
(BigInt(1000 - 3) * (BigInt(outSup) - BigInt(amount)));
|
|
1243
|
-
return {
|
|
1244
|
-
swapOutput,
|
|
1245
|
-
swapInput
|
|
1246
|
-
};
|
|
1247
|
-
}
|
|
1248
|
-
getTmpPoolId() {
|
|
1249
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1250
|
-
const state = yield this.getAppState();
|
|
1251
|
-
return state['tp'];
|
|
1252
|
-
});
|
|
1253
|
-
}
|
|
1254
|
-
getTmpStablePoolId() {
|
|
1255
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1256
|
-
const state = yield this.getAppState();
|
|
1257
|
-
return state['tsp'];
|
|
1258
|
-
});
|
|
1259
|
-
}
|
|
1260
|
-
getAppState() {
|
|
1261
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1262
|
-
const appInfo = yield this.client.getApplicationByID(this.appId).do();
|
|
1263
|
-
const stateArray = appInfo['params']['global-state'];
|
|
1264
|
-
const state = (0, utils_1.decodeStateArray)(stateArray);
|
|
1265
|
-
return state;
|
|
1266
|
-
});
|
|
1267
|
-
}
|
|
1268
|
-
checkIsPoolExist(assetA, assetB) {
|
|
1269
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1270
|
-
try {
|
|
1271
|
-
const poolId = yield this.getPoolIdByAssets(assetA, assetB);
|
|
1272
|
-
if (poolId)
|
|
1273
|
-
return true;
|
|
1274
|
-
else
|
|
1275
|
-
return false;
|
|
1276
|
-
}
|
|
1277
|
-
catch (e) {
|
|
1278
|
-
return false;
|
|
1279
|
-
}
|
|
1280
|
-
});
|
|
1281
|
-
}
|
|
1282
|
-
getAsset(assetId) {
|
|
1283
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1284
|
-
if (this.assetsCache[assetId]) {
|
|
1285
|
-
return this.assetsCache[assetId];
|
|
1286
|
-
}
|
|
1287
|
-
else {
|
|
1288
|
-
const asset = yield this.client.getAssetByID(assetId).do();
|
|
1289
|
-
this.assetsCache[assetId] = asset;
|
|
1290
|
-
return asset;
|
|
1291
|
-
}
|
|
1292
|
-
});
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
exports.AmmClient = AmmClient;
|