@indigo-labs/indigo-sdk 0.5.5 → 0.5.6
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/package.json +11 -1
- package/.claude/settings.local.json +0 -7
- package/.github/workflows/ci.yml +0 -66
- package/.husky/pre-commit +0 -1
- package/.nvmrc +0 -1
- package/.prettierignore +0 -1
- package/.prettierrc +0 -6
- package/eslint.config.mjs +0 -42
- package/scripts/bench.sh +0 -62
- package/scripts/run-repeat.sh +0 -22
- package/src/contracts/cdp/helpers.ts +0 -173
- package/src/contracts/cdp/scripts.ts +0 -70
- package/src/contracts/cdp/transactions.ts +0 -1584
- package/src/contracts/cdp/types-new.ts +0 -277
- package/src/contracts/cdp/types.ts +0 -43
- package/src/contracts/cdp-creator/queries.ts +0 -30
- package/src/contracts/cdp-creator/scripts.ts +0 -45
- package/src/contracts/cdp-creator/types-new.ts +0 -50
- package/src/contracts/cdp-creator/types.ts +0 -24
- package/src/contracts/collector/scripts.ts +0 -32
- package/src/contracts/collector/transactions.ts +0 -50
- package/src/contracts/collector/types-new.ts +0 -17
- package/src/contracts/execute/scripts.ts +0 -57
- package/src/contracts/execute/types-new.ts +0 -44
- package/src/contracts/execute/types.ts +0 -24
- package/src/contracts/gov/helpers.ts +0 -351
- package/src/contracts/gov/scripts.ts +0 -41
- package/src/contracts/gov/transactions.ts +0 -1607
- package/src/contracts/gov/types-new.ts +0 -268
- package/src/contracts/gov/types.ts +0 -22
- package/src/contracts/iasset/helpers.ts +0 -170
- package/src/contracts/iasset/queries.ts +0 -102
- package/src/contracts/iasset/scripts.ts +0 -38
- package/src/contracts/iasset/types.ts +0 -154
- package/src/contracts/initialize/actions.ts +0 -789
- package/src/contracts/initialize/helpers.ts +0 -616
- package/src/contracts/initialize/types.ts +0 -116
- package/src/contracts/interest-collection/helpers.ts +0 -19
- package/src/contracts/interest-collection/queries.ts +0 -66
- package/src/contracts/interest-collection/scripts.ts +0 -44
- package/src/contracts/interest-collection/transactions.ts +0 -433
- package/src/contracts/interest-collection/types-new.ts +0 -50
- package/src/contracts/interest-collection/types.ts +0 -26
- package/src/contracts/interest-oracle/helpers.ts +0 -61
- package/src/contracts/interest-oracle/scripts.ts +0 -18
- package/src/contracts/interest-oracle/transactions.ts +0 -151
- package/src/contracts/interest-oracle/types-new.ts +0 -32
- package/src/contracts/interest-oracle/types.ts +0 -16
- package/src/contracts/one-shot/scripts.ts +0 -12
- package/src/contracts/one-shot/transactions.ts +0 -66
- package/src/contracts/one-shot/types.ts +0 -22
- package/src/contracts/poll/helpers.ts +0 -37
- package/src/contracts/poll/scripts.ts +0 -71
- package/src/contracts/poll/types-poll-manager.ts +0 -20
- package/src/contracts/poll/types-poll-new.ts +0 -196
- package/src/contracts/poll/types-poll-shard.ts +0 -16
- package/src/contracts/price-oracle/helpers.ts +0 -30
- package/src/contracts/price-oracle/scripts.ts +0 -18
- package/src/contracts/price-oracle/transactions.ts +0 -115
- package/src/contracts/price-oracle/types-new.ts +0 -50
- package/src/contracts/price-oracle/types.ts +0 -16
- package/src/contracts/pyth-feed/helpers.ts +0 -82
- package/src/contracts/pyth-feed/scripts.ts +0 -15
- package/src/contracts/pyth-feed/types.ts +0 -181
- package/src/contracts/rob/helpers.ts +0 -666
- package/src/contracts/rob/scripts.ts +0 -35
- package/src/contracts/rob/transactions.ts +0 -423
- package/src/contracts/rob/types-new.ts +0 -128
- package/src/contracts/rob/types.ts +0 -16
- package/src/contracts/rob-leverage/helpers.ts +0 -422
- package/src/contracts/rob-leverage/transactions.ts +0 -368
- package/src/contracts/stability-pool/helpers.ts +0 -798
- package/src/contracts/stability-pool/queries.ts +0 -132
- package/src/contracts/stability-pool/scripts.ts +0 -51
- package/src/contracts/stability-pool/transactions.ts +0 -921
- package/src/contracts/stability-pool/types-new.ts +0 -385
- package/src/contracts/stability-pool/types.ts +0 -25
- package/src/contracts/stableswap/helpers.ts +0 -507
- package/src/contracts/stableswap/scripts.ts +0 -37
- package/src/contracts/stableswap/transactions.ts +0 -475
- package/src/contracts/stableswap/types-new.ts +0 -131
- package/src/contracts/stableswap/types.ts +0 -17
- package/src/contracts/staking/helpers.ts +0 -136
- package/src/contracts/staking/scripts.ts +0 -41
- package/src/contracts/staking/transactions.ts +0 -349
- package/src/contracts/staking/types-new.ts +0 -137
- package/src/contracts/staking/types.ts +0 -17
- package/src/contracts/treasury/helpers.ts +0 -21
- package/src/contracts/treasury/queries.ts +0 -100
- package/src/contracts/treasury/scripts.ts +0 -27
- package/src/contracts/treasury/transactions.ts +0 -334
- package/src/contracts/treasury/types-new.ts +0 -69
- package/src/contracts/treasury/types.ts +0 -14
- package/src/contracts/version-registry/scripts.ts +0 -29
- package/src/contracts/version-registry/types-new.ts +0 -18
- package/src/contracts/version-registry/types.ts +0 -17
- package/src/index.ts +0 -99
- package/src/scripts/always-fail-validator.ts +0 -7
- package/src/scripts/auth-token-policy.ts +0 -24
- package/src/scripts/iasset-policy.ts +0 -23
- package/src/types/evolution-schema-options.ts +0 -16
- package/src/types/generic.ts +0 -52
- package/src/types/multisig.ts +0 -48
- package/src/types/on-chain-decimal.ts +0 -57
- package/src/types/rational.ts +0 -76
- package/src/types/system-params.ts +0 -463
- package/src/utils/array-utils.ts +0 -108
- package/src/utils/bigint-utils.ts +0 -35
- package/src/utils/helper-txs.ts +0 -31
- package/src/utils/indigo-helpers.ts +0 -17
- package/src/utils/lucid-utils.ts +0 -125
- package/src/utils/oracle-helpers.ts +0 -62
- package/src/utils/pyth/decode.ts +0 -223
- package/src/utils/pyth/encode.ts +0 -262
- package/src/utils/pyth/index.ts +0 -14
- package/src/utils/pyth/types.ts +0 -87
- package/src/utils/time-helpers.ts +0 -4
- package/src/utils/utils.ts +0 -25
- package/src/validators/always-succeed-validator.ts +0 -6
- package/src/validators/cdp-creator-validator.ts +0 -7
- package/src/validators/cdp-redeem-validator.ts +0 -7
- package/src/validators/cdp-validator.ts +0 -7
- package/src/validators/collector-validator.ts +0 -7
- package/src/validators/execute-validator.ts +0 -7
- package/src/validators/governance-validator.ts +0 -7
- package/src/validators/iasset-validator.ts +0 -7
- package/src/validators/interest-collection-validator.ts +0 -7
- package/src/validators/interest-oracle-validator.ts +0 -7
- package/src/validators/one-shot-policy.ts +0 -7
- package/src/validators/poll-manager-validator.ts +0 -7
- package/src/validators/poll-shard-validator.ts +0 -7
- package/src/validators/price-oracle-validator.ts +0 -7
- package/src/validators/pyth-feed-validator.ts +0 -7
- package/src/validators/rob-validator.ts +0 -7
- package/src/validators/stability-pool-validator.ts +0 -7
- package/src/validators/stableswap-validator.ts +0 -7
- package/src/validators/staking-validator.ts +0 -7
- package/src/validators/treasury-validator.ts +0 -7
- package/src/validators/version-record-policy.ts +0 -7
- package/src/validators/version-registry-validator.ts +0 -7
- package/tests/always-succeed/script.ts +0 -7
- package/tests/array-utils.test.ts +0 -92
- package/tests/bigint-utils.test.ts +0 -41
- package/tests/cdp/actions.ts +0 -680
- package/tests/cdp/cdp-helpers.ts +0 -55
- package/tests/cdp/cdp-queries.ts +0 -423
- package/tests/cdp/cdp.test.ts +0 -6730
- package/tests/cdp/transactions-mutated.ts +0 -1733
- package/tests/data/system-params.json +0 -1155
- package/tests/datums.test.ts +0 -302
- package/tests/endpoints/initialize.ts +0 -78
- package/tests/endpoints/interest-collector.ts +0 -37
- package/tests/endpoints/treasury.ts +0 -70
- package/tests/gov/actions.ts +0 -381
- package/tests/gov/gov.test.ts +0 -5147
- package/tests/gov/governance-queries.ts +0 -37
- package/tests/hash-checks.test.ts +0 -112
- package/tests/indigo-test-helpers.ts +0 -99
- package/tests/initialize.test.ts +0 -79
- package/tests/interest-calculations.test.ts +0 -120
- package/tests/interest-collection/interest-collection.test.ts +0 -843
- package/tests/interest-collection/transactions-mutated.ts +0 -260
- package/tests/interest-oracle.test.ts +0 -93
- package/tests/mock/assets-mock.ts +0 -243
- package/tests/mock/protocol-params-mock.ts +0 -21
- package/tests/price-oracle/actions.ts +0 -161
- package/tests/price-oracle/price-oracle-queries.ts +0 -12
- package/tests/price-oracle/price-oracle.test.ts +0 -228
- package/tests/price-oracle/transactions-mutated.ts +0 -59
- package/tests/pyth/endpoints.ts +0 -96
- package/tests/pyth/helpers.ts +0 -37
- package/tests/pyth/pyth-encoding.test.ts +0 -376
- package/tests/pyth/pyth-feeds.test.ts +0 -943
- package/tests/pyth/pyth-indigo.test.ts +0 -505
- package/tests/pyth/pyth.test.ts +0 -299
- package/tests/queries/collector-queries.ts +0 -27
- package/tests/queries/execute-queries.ts +0 -47
- package/tests/queries/iasset-queries.ts +0 -149
- package/tests/queries/interest-oracle-queries.ts +0 -12
- package/tests/queries/poll-queries.ts +0 -97
- package/tests/queries/staking-queries.ts +0 -54
- package/tests/rob/actions.ts +0 -56
- package/tests/rob/rob-leverage.test.ts +0 -2555
- package/tests/rob/rob-queries.ts +0 -95
- package/tests/rob/rob.test.ts +0 -3677
- package/tests/rob/transactions-mutated.ts +0 -844
- package/tests/script-size.test.ts +0 -240
- package/tests/setup.ts +0 -135
- package/tests/stability-pool/actions.ts +0 -229
- package/tests/stability-pool.test.ts +0 -6491
- package/tests/stableswap/stableswap-actions.ts +0 -83
- package/tests/stableswap/stableswap-queries.ts +0 -98
- package/tests/stableswap/stableswap.test.ts +0 -4471
- package/tests/stableswap/transactions-mutated.ts +0 -348
- package/tests/staking.test.ts +0 -172
- package/tests/test-helpers.ts +0 -94
- package/tests/treasury/actions.ts +0 -67
- package/tests/treasury/treasury.test.ts +0 -320
- package/tests/utils/asserts.ts +0 -87
- package/tests/utils/benchmark-utils.ts +0 -130
- package/tests/utils/index.ts +0 -168
- package/tsconfig.build.json +0 -4
- package/tsconfig.json +0 -27
- package/vitest.config.ts +0 -11
|
@@ -1,666 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
addAssets,
|
|
3
|
-
Assets,
|
|
4
|
-
fromHex,
|
|
5
|
-
toHex,
|
|
6
|
-
TxBuilder,
|
|
7
|
-
UTxO,
|
|
8
|
-
} from '@lucid-evolution/lucid';
|
|
9
|
-
import {
|
|
10
|
-
RobDatum,
|
|
11
|
-
RobOrderType,
|
|
12
|
-
parseRobDatumOrThrow,
|
|
13
|
-
serialiseRobDatum,
|
|
14
|
-
serialiseRobRedeemer,
|
|
15
|
-
} from './types-new';
|
|
16
|
-
import { calculateFeeFromRatio } from '../../utils/indigo-helpers';
|
|
17
|
-
import {
|
|
18
|
-
BigIntOrd,
|
|
19
|
-
fromDecimal,
|
|
20
|
-
sum,
|
|
21
|
-
zeroNegatives,
|
|
22
|
-
} from '../../utils/bigint-utils';
|
|
23
|
-
import {
|
|
24
|
-
readonlyArray as RA,
|
|
25
|
-
array as A,
|
|
26
|
-
function as F,
|
|
27
|
-
option as O,
|
|
28
|
-
ord as Ord,
|
|
29
|
-
} from 'fp-ts';
|
|
30
|
-
import { SystemParams } from '../../types/system-params';
|
|
31
|
-
import { match, P } from 'ts-pattern';
|
|
32
|
-
import { getInlineDatumOrThrow } from '../../utils/lucid-utils';
|
|
33
|
-
import {
|
|
34
|
-
adaAssetClass,
|
|
35
|
-
AssetClass,
|
|
36
|
-
assetClassValueOf,
|
|
37
|
-
isSameAssetClass,
|
|
38
|
-
lovelacesAmt,
|
|
39
|
-
mkAssetsOf,
|
|
40
|
-
} from '@3rd-eye-labs/cardano-offchain-common';
|
|
41
|
-
import {
|
|
42
|
-
Rational,
|
|
43
|
-
rationalFloor,
|
|
44
|
-
rationalFromInt,
|
|
45
|
-
rationalMul,
|
|
46
|
-
rationalToFloat,
|
|
47
|
-
} from '../../types/rational';
|
|
48
|
-
import { insertSorted, shuffle } from '../../utils/array-utils';
|
|
49
|
-
import { iassetValueOfCollateral } from '../cdp/helpers';
|
|
50
|
-
import { OracleIdx } from '../price-oracle/types-new';
|
|
51
|
-
import Decimal from 'decimal.js';
|
|
52
|
-
|
|
53
|
-
export const MIN_ROB_COLLATERAL_AMT = 3_000_000n;
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* The maximum of redemptions for a Tx that is doing only sell order redemptions.
|
|
57
|
-
* Based on the benchmarks.
|
|
58
|
-
*/
|
|
59
|
-
export const MAX_SELL_ROB_REDEMPTIONS_COUNT = 18;
|
|
60
|
-
/**
|
|
61
|
-
* The maximum of redemptions for a Tx that is doing only buy order redemptions.
|
|
62
|
-
* Based on the benchmarks.
|
|
63
|
-
*/
|
|
64
|
-
export const MAX_BUY_ROB_REDEMPTIONS_COUNT = 20;
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Helper for ROB redemptions. A redeemer is selling iAssets against
|
|
68
|
-
* a buy order, i.e. buying a collateral asset.
|
|
69
|
-
* The return is the amount of collateral asset he buys.
|
|
70
|
-
*/
|
|
71
|
-
export function calculatePurchaseAmtWhenRobBuyOrder(
|
|
72
|
-
sellIassetAmt: bigint,
|
|
73
|
-
redemptionReimbursementRatio: Rational,
|
|
74
|
-
price: Rational,
|
|
75
|
-
): bigint {
|
|
76
|
-
const reimbursementIAsset = calculateFeeFromRatio(
|
|
77
|
-
redemptionReimbursementRatio,
|
|
78
|
-
sellIassetAmt,
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
const collateralForRedemption = rationalFloor(
|
|
82
|
-
rationalMul(rationalFromInt(sellIassetAmt - reimbursementIAsset), price),
|
|
83
|
-
);
|
|
84
|
-
|
|
85
|
-
return collateralForRedemption;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* A redeemer is purchasing given collateral amount against buy order.
|
|
90
|
-
* Calculate what is the amount of iAsset the user sells/spends.
|
|
91
|
-
*/
|
|
92
|
-
export function calculateSpendAmtWhenRobBuyOrder(
|
|
93
|
-
purchaseCollateralAmt: bigint,
|
|
94
|
-
redemptionReimbursementRatio: Rational,
|
|
95
|
-
price: Rational,
|
|
96
|
-
): bigint {
|
|
97
|
-
const priceDecimal = Decimal(price.numerator).div(price.denominator);
|
|
98
|
-
const reimbRatio = Decimal(redemptionReimbursementRatio.numerator).div(
|
|
99
|
-
redemptionReimbursementRatio.denominator,
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
// TODO: make corrections here in case we can be ceiling this number instead.
|
|
103
|
-
// We want to be flooring here so that we don't go over the collateral to spend.
|
|
104
|
-
// Flooring multiple times is necessary here otherwise we could go over the collateral available.
|
|
105
|
-
// iassets = floor(collateral / price) / floor(1 - reimbursement fee)
|
|
106
|
-
return fromDecimal(
|
|
107
|
-
Decimal(purchaseCollateralAmt)
|
|
108
|
-
.div(priceDecimal)
|
|
109
|
-
.floor()
|
|
110
|
-
.div(Decimal(1).minus(reimbRatio))
|
|
111
|
-
.floor(),
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Helper for ROB redemptions. A redeemer is selling collateral against
|
|
117
|
-
* a sell order, i.e. buying iassets.
|
|
118
|
-
* The return is the amount of iassets he buys.
|
|
119
|
-
*/
|
|
120
|
-
export function calculatePurchaseAmtWhenRobSellOrder(
|
|
121
|
-
sellCollateralAmt: bigint,
|
|
122
|
-
redemptionReimbursementRatio: Rational,
|
|
123
|
-
price: Rational,
|
|
124
|
-
): bigint {
|
|
125
|
-
const reimbursementCollateral = calculateFeeFromRatio(
|
|
126
|
-
redemptionReimbursementRatio,
|
|
127
|
-
sellCollateralAmt,
|
|
128
|
-
);
|
|
129
|
-
|
|
130
|
-
const redeemedIAssetAmt = iassetValueOfCollateral(
|
|
131
|
-
sellCollateralAmt - reimbursementCollateral,
|
|
132
|
-
price,
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
return redeemedIAssetAmt;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* A redeemer is purchasing given iasset amount against sell order.
|
|
140
|
-
* Calculate what is the amount of collateral the user sells/spends.
|
|
141
|
-
*/
|
|
142
|
-
export function calculateSpendAmtWhenRobSellOrder(
|
|
143
|
-
purchaseIassetAmt: bigint,
|
|
144
|
-
redemptionReimbursementRatio: Rational,
|
|
145
|
-
price: Rational,
|
|
146
|
-
): bigint {
|
|
147
|
-
const priceDecimal = Decimal(price.numerator).div(price.denominator);
|
|
148
|
-
const reimbRatio = Decimal(redemptionReimbursementRatio.numerator).div(
|
|
149
|
-
redemptionReimbursementRatio.denominator,
|
|
150
|
-
);
|
|
151
|
-
|
|
152
|
-
// collateral = floor(iasset * price) / floor(1 - reimbursement fee)
|
|
153
|
-
return fromDecimal(
|
|
154
|
-
Decimal(purchaseIassetAmt)
|
|
155
|
-
.mul(priceDecimal)
|
|
156
|
-
.floor()
|
|
157
|
-
.div(Decimal(1).minus(reimbRatio))
|
|
158
|
-
.floor(),
|
|
159
|
-
);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* The amount of collateral asset available in the ROB when buy order. In case of ADA, take
|
|
164
|
-
* into account the min UTXO collateral.
|
|
165
|
-
*/
|
|
166
|
-
export function robCollateralAmtToSpend(
|
|
167
|
-
robAssets: Assets,
|
|
168
|
-
robOrderType: RobOrderType,
|
|
169
|
-
): bigint {
|
|
170
|
-
return match(robOrderType)
|
|
171
|
-
.returnType<bigint>()
|
|
172
|
-
.with({ BuyIAssetOrder: P.select() }, (content) => {
|
|
173
|
-
if (isSameAssetClass(adaAssetClass, content.collateralAsset)) {
|
|
174
|
-
return zeroNegatives(lovelacesAmt(robAssets) - MIN_ROB_COLLATERAL_AMT);
|
|
175
|
-
} else {
|
|
176
|
-
return assetClassValueOf(robAssets, content.collateralAsset);
|
|
177
|
-
}
|
|
178
|
-
})
|
|
179
|
-
.otherwise(() => {
|
|
180
|
-
throw new Error('Collateral to spend is relevant only for Buy orders.');
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* The amount if iassets available in ROB when sell order.
|
|
186
|
-
*/
|
|
187
|
-
export function robIAssetAmtToSpend(
|
|
188
|
-
robAssets: Assets,
|
|
189
|
-
robOrderType: RobOrderType,
|
|
190
|
-
/**
|
|
191
|
-
* This has to be assetclass having policyID of Indigo iAssets,
|
|
192
|
-
* and the asset name being the ROB datum iasset.
|
|
193
|
-
*/
|
|
194
|
-
robIasset: AssetClass,
|
|
195
|
-
): bigint {
|
|
196
|
-
return match(robOrderType)
|
|
197
|
-
.returnType<bigint>()
|
|
198
|
-
.with({ SellIAssetOrder: P.any }, (_) => {
|
|
199
|
-
return assetClassValueOf(robAssets, robIasset);
|
|
200
|
-
})
|
|
201
|
-
.otherwise(() => {
|
|
202
|
-
throw new Error('IAssets to spend is relevant only for Sell orders.');
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Amount to spend from the ROB universal for Buy and sell orders.
|
|
208
|
-
*/
|
|
209
|
-
export function robAmtToSpend(
|
|
210
|
-
robAssets: Assets,
|
|
211
|
-
robOrderType: RobOrderType,
|
|
212
|
-
/**
|
|
213
|
-
* This has to be assetclass having policyID of Indigo iAssets,
|
|
214
|
-
* and the asset name being the ROB datum iasset.
|
|
215
|
-
*/
|
|
216
|
-
robIasset: AssetClass,
|
|
217
|
-
): bigint {
|
|
218
|
-
return match(robOrderType)
|
|
219
|
-
.with({ BuyIAssetOrder: P.any }, () =>
|
|
220
|
-
robCollateralAmtToSpend(robAssets, robOrderType),
|
|
221
|
-
)
|
|
222
|
-
.with({ SellIAssetOrder: P.any }, () =>
|
|
223
|
-
robIAssetAmtToSpend(robAssets, robOrderType, robIasset),
|
|
224
|
-
)
|
|
225
|
-
.exhaustive();
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
type FilledResult = { asset: AssetClass; filledAmt: bigint };
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* The assets that have filled the order and are able to be claimed.
|
|
232
|
-
*/
|
|
233
|
-
export function robBuyOrderFilledAssets(
|
|
234
|
-
robAssets: Assets,
|
|
235
|
-
robOrderType: RobOrderType,
|
|
236
|
-
/**
|
|
237
|
-
* This has to be assetclass having policyID of Indigo iAssets,
|
|
238
|
-
* and the asset name being the ROB datum iasset.
|
|
239
|
-
*/
|
|
240
|
-
robIasset: AssetClass,
|
|
241
|
-
): FilledResult {
|
|
242
|
-
return match(robOrderType)
|
|
243
|
-
.returnType<FilledResult>()
|
|
244
|
-
.with({ BuyIAssetOrder: P.any }, () => {
|
|
245
|
-
return {
|
|
246
|
-
asset: robIasset,
|
|
247
|
-
filledAmt: assetClassValueOf(robAssets, robIasset),
|
|
248
|
-
};
|
|
249
|
-
})
|
|
250
|
-
.otherwise(() => {
|
|
251
|
-
throw new Error('Expected only buy order.');
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* The assets that have filled the order and are able to be claimed.
|
|
257
|
-
*/
|
|
258
|
-
export function robSellOrderFilledAssets(
|
|
259
|
-
robAssets: Assets,
|
|
260
|
-
robOrderType: RobOrderType,
|
|
261
|
-
): FilledResult[] {
|
|
262
|
-
return match(robOrderType)
|
|
263
|
-
.returnType<FilledResult[]>()
|
|
264
|
-
.with({ SellIAssetOrder: P.select() }, (content) => {
|
|
265
|
-
return content.allowedCollateralAssets.map(([asset, _]) => {
|
|
266
|
-
return {
|
|
267
|
-
asset: asset,
|
|
268
|
-
filledAmt:
|
|
269
|
-
assetClassValueOf(robAssets, asset) -
|
|
270
|
-
(isSameAssetClass(asset, adaAssetClass)
|
|
271
|
-
? MIN_ROB_COLLATERAL_AMT
|
|
272
|
-
: 0n),
|
|
273
|
-
} satisfies FilledResult;
|
|
274
|
-
});
|
|
275
|
-
})
|
|
276
|
-
.otherwise(() => {
|
|
277
|
-
throw new Error('Expected only sell order.');
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
export function robBuyOrderSummary(
|
|
282
|
-
robAssets: Assets,
|
|
283
|
-
robOrderType: RobOrderType,
|
|
284
|
-
oraclePrice: Rational,
|
|
285
|
-
): {
|
|
286
|
-
/**
|
|
287
|
-
* The amount that can be spent from the ROB.
|
|
288
|
-
*/
|
|
289
|
-
redeemableCollateral: bigint;
|
|
290
|
-
/**
|
|
291
|
-
* The amount paid to the ROB when everything redeemed.
|
|
292
|
-
*/
|
|
293
|
-
payoutIAsset: bigint;
|
|
294
|
-
} {
|
|
295
|
-
const redeemable = robCollateralAmtToSpend(robAssets, robOrderType);
|
|
296
|
-
|
|
297
|
-
// TODO: this is incorrect since it doesn't take into account the reimbursement ratio.
|
|
298
|
-
const payoutAmt = iassetValueOfCollateral(redeemable, oraclePrice);
|
|
299
|
-
|
|
300
|
-
return {
|
|
301
|
-
redeemableCollateral: redeemable,
|
|
302
|
-
payoutIAsset: payoutAmt,
|
|
303
|
-
};
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* In case it's applied to a sell order instead, it will throw an error.
|
|
308
|
-
*/
|
|
309
|
-
export function isBuyOrderFullyRedeemed(
|
|
310
|
-
robAssets: Assets,
|
|
311
|
-
robOrderType: RobOrderType,
|
|
312
|
-
oraclePrice: Rational,
|
|
313
|
-
): boolean {
|
|
314
|
-
const summary = robBuyOrderSummary(robAssets, robOrderType, oraclePrice);
|
|
315
|
-
|
|
316
|
-
return summary.redeemableCollateral <= 0n || summary.payoutIAsset <= 0n;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/**
|
|
320
|
-
* Use the limit prices to decide fully redeemed.
|
|
321
|
-
*/
|
|
322
|
-
export function isFullyRedeemed(
|
|
323
|
-
robAssets: Assets,
|
|
324
|
-
robOrderType: RobOrderType,
|
|
325
|
-
/**
|
|
326
|
-
* This has to be assetclass having policyID of Indigo iAssets,
|
|
327
|
-
* and the asset name being the ROB datum iasset.
|
|
328
|
-
*/
|
|
329
|
-
robIasset: AssetClass,
|
|
330
|
-
): boolean {
|
|
331
|
-
return match(robOrderType)
|
|
332
|
-
.returnType<boolean>()
|
|
333
|
-
.with({ BuyIAssetOrder: P.select() }, (content) =>
|
|
334
|
-
isBuyOrderFullyRedeemed(robAssets, robOrderType, content.maxPrice),
|
|
335
|
-
)
|
|
336
|
-
|
|
337
|
-
.with({ SellIAssetOrder: P.select() }, (content) => {
|
|
338
|
-
const iassetToSpend = robIAssetAmtToSpend(
|
|
339
|
-
robAssets,
|
|
340
|
-
robOrderType,
|
|
341
|
-
robIasset,
|
|
342
|
-
);
|
|
343
|
-
|
|
344
|
-
const payoutAmts = content.allowedCollateralAssets.map((c) =>
|
|
345
|
-
rationalFloor(rationalMul(rationalFromInt(iassetToSpend), c[1])),
|
|
346
|
-
);
|
|
347
|
-
|
|
348
|
-
return (
|
|
349
|
-
iassetToSpend <= 0n ||
|
|
350
|
-
// When for every allowed collateral asset the payout would be 0
|
|
351
|
-
payoutAmts.every((amt) => amt <= 0n)
|
|
352
|
-
);
|
|
353
|
-
})
|
|
354
|
-
.exhaustive();
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
/**
|
|
358
|
-
* Right now we allow multi redemptions when the collateral asset, iasset pair is the same.
|
|
359
|
-
* The on-chain however should allow even other combinations.
|
|
360
|
-
*/
|
|
361
|
-
export function buildRedemptionsTx(
|
|
362
|
-
/**
|
|
363
|
-
* The tuple represents the ROB UTXO and the amount to payout for a redemption. In case of buy order,
|
|
364
|
-
* it's denominated in iAssets, in case of sell order, it's denominated in collateral asset.
|
|
365
|
-
*/
|
|
366
|
-
redemptions: [UTxO, bigint][],
|
|
367
|
-
iasset: Uint8Array<ArrayBufferLike>,
|
|
368
|
-
collateralAsset: AssetClass,
|
|
369
|
-
price: Rational,
|
|
370
|
-
redemptionReimbursementRatio: Rational,
|
|
371
|
-
sysParams: SystemParams,
|
|
372
|
-
tx: TxBuilder,
|
|
373
|
-
/**
|
|
374
|
-
* The number of Tx outputs before these new ones.
|
|
375
|
-
*/
|
|
376
|
-
txOutputsBeforeCount: bigint,
|
|
377
|
-
collateralAssetRefInputIdx: bigint,
|
|
378
|
-
iassetRefInputIdx: bigint,
|
|
379
|
-
oracleIdx: OracleIdx,
|
|
380
|
-
): TxBuilder {
|
|
381
|
-
return F.pipe(
|
|
382
|
-
redemptions,
|
|
383
|
-
A.reduceWithIndex<[UTxO, bigint], TxBuilder>(
|
|
384
|
-
tx,
|
|
385
|
-
(idx, acc, [robUtxo, payoutAmt]) => {
|
|
386
|
-
const robDatum = parseRobDatumOrThrow(getInlineDatumOrThrow(robUtxo));
|
|
387
|
-
|
|
388
|
-
if (toHex(robDatum.iasset) !== toHex(iasset)) {
|
|
389
|
-
throw new Error('Only same iAsset');
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
const [robOutputVal, sellOrderAllowedAssetsIdx] = match(
|
|
393
|
-
robDatum.orderType,
|
|
394
|
-
)
|
|
395
|
-
.returnType<[Assets, bigint]>()
|
|
396
|
-
.with({ BuyIAssetOrder: P.select() }, (content) => {
|
|
397
|
-
if (!isSameAssetClass(content.collateralAsset, collateralAsset)) {
|
|
398
|
-
throw new Error('Only same collateral asset');
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
const payoutIAssetAmt = payoutAmt;
|
|
402
|
-
|
|
403
|
-
const collateralForRedemption = calculatePurchaseAmtWhenRobBuyOrder(
|
|
404
|
-
payoutIAssetAmt,
|
|
405
|
-
redemptionReimbursementRatio,
|
|
406
|
-
price,
|
|
407
|
-
);
|
|
408
|
-
|
|
409
|
-
const resultVal = addAssets(
|
|
410
|
-
robUtxo.assets,
|
|
411
|
-
mkAssetsOf(collateralAsset, -collateralForRedemption),
|
|
412
|
-
mkAssetsOf(
|
|
413
|
-
{
|
|
414
|
-
currencySymbol: fromHex(
|
|
415
|
-
sysParams.robParams.iassetPolicyId.unCurrencySymbol,
|
|
416
|
-
),
|
|
417
|
-
tokenName: robDatum.iasset,
|
|
418
|
-
},
|
|
419
|
-
payoutIAssetAmt,
|
|
420
|
-
),
|
|
421
|
-
);
|
|
422
|
-
|
|
423
|
-
return [resultVal, 0n];
|
|
424
|
-
})
|
|
425
|
-
.with({ SellIAssetOrder: P.select() }, (content) => {
|
|
426
|
-
const allowedAssetIdx = F.pipe(
|
|
427
|
-
content.allowedCollateralAssets,
|
|
428
|
-
RA.findIndex(([asset, _]) =>
|
|
429
|
-
isSameAssetClass(asset, collateralAsset),
|
|
430
|
-
),
|
|
431
|
-
O.getOrElse<number>(() => {
|
|
432
|
-
throw new Error("Doesn't allow required collateral asset.");
|
|
433
|
-
}),
|
|
434
|
-
);
|
|
435
|
-
|
|
436
|
-
const payoutCollateralAmt = payoutAmt;
|
|
437
|
-
|
|
438
|
-
const redeemedIAssetAmt = calculatePurchaseAmtWhenRobSellOrder(
|
|
439
|
-
payoutCollateralAmt,
|
|
440
|
-
redemptionReimbursementRatio,
|
|
441
|
-
price,
|
|
442
|
-
);
|
|
443
|
-
|
|
444
|
-
const resultVal = addAssets(
|
|
445
|
-
robUtxo.assets,
|
|
446
|
-
mkAssetsOf(collateralAsset, payoutCollateralAmt),
|
|
447
|
-
mkAssetsOf(
|
|
448
|
-
{
|
|
449
|
-
currencySymbol: fromHex(
|
|
450
|
-
sysParams.robParams.iassetPolicyId.unCurrencySymbol,
|
|
451
|
-
),
|
|
452
|
-
tokenName: robDatum.iasset,
|
|
453
|
-
},
|
|
454
|
-
-redeemedIAssetAmt,
|
|
455
|
-
),
|
|
456
|
-
);
|
|
457
|
-
|
|
458
|
-
return [resultVal, BigInt(allowedAssetIdx)];
|
|
459
|
-
})
|
|
460
|
-
.exhaustive();
|
|
461
|
-
|
|
462
|
-
if (lovelacesAmt(robOutputVal) < MIN_ROB_COLLATERAL_AMT) {
|
|
463
|
-
throw new Error(
|
|
464
|
-
'Redeeming more than available or selected ROB was incorrectly initialised.',
|
|
465
|
-
);
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
return acc
|
|
469
|
-
.collectFrom([robUtxo], {
|
|
470
|
-
kind: 'self',
|
|
471
|
-
makeRedeemer: (ownIdx) =>
|
|
472
|
-
serialiseRobRedeemer({
|
|
473
|
-
Redeem: {
|
|
474
|
-
ownInputIdx: ownIdx,
|
|
475
|
-
collateralAssetRefInputIdx: collateralAssetRefInputIdx,
|
|
476
|
-
iassetRefInputIdx: iassetRefInputIdx,
|
|
477
|
-
continuingOutputIdx: txOutputsBeforeCount + BigInt(idx),
|
|
478
|
-
sellOrderAllowedAssetsIdx: sellOrderAllowedAssetsIdx,
|
|
479
|
-
priceOracleIdx: oracleIdx,
|
|
480
|
-
},
|
|
481
|
-
}),
|
|
482
|
-
})
|
|
483
|
-
.pay.ToContract(
|
|
484
|
-
robUtxo.address,
|
|
485
|
-
{
|
|
486
|
-
kind: 'inline',
|
|
487
|
-
value: serialiseRobDatum({
|
|
488
|
-
...robDatum,
|
|
489
|
-
robRefInput: {
|
|
490
|
-
outputIndex: BigInt(robUtxo.outputIndex),
|
|
491
|
-
txHash: fromHex(robUtxo.txHash),
|
|
492
|
-
},
|
|
493
|
-
}),
|
|
494
|
-
},
|
|
495
|
-
robOutputVal,
|
|
496
|
-
);
|
|
497
|
-
},
|
|
498
|
-
),
|
|
499
|
-
);
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
/**
|
|
503
|
-
* Given all available LRP UTXOs, calculate total available collateral that can be redeemed.
|
|
504
|
-
* Taking into account incorrectly initialised LRPs (without base collateral) and max number of ROBs.
|
|
505
|
-
*/
|
|
506
|
-
export function calculateTotalCollateralForRedemption(
|
|
507
|
-
iasset: Uint8Array<ArrayBufferLike>,
|
|
508
|
-
collateralAsset: AssetClass,
|
|
509
|
-
iassetPrice: Rational,
|
|
510
|
-
allRobs: [UTxO, RobDatum][],
|
|
511
|
-
/**
|
|
512
|
-
* How many LRPs can be redeemed in a single Tx.
|
|
513
|
-
*/
|
|
514
|
-
maxRobsInTx: number,
|
|
515
|
-
): bigint {
|
|
516
|
-
return F.pipe(
|
|
517
|
-
allRobs,
|
|
518
|
-
A.filterMap(([utxo, datum]) => {
|
|
519
|
-
const isCorrectOrder = match(datum.orderType)
|
|
520
|
-
.returnType<boolean>()
|
|
521
|
-
.with(
|
|
522
|
-
{ BuyIAssetOrder: P.select() },
|
|
523
|
-
(content) =>
|
|
524
|
-
isSameAssetClass(content.collateralAsset, collateralAsset) &&
|
|
525
|
-
rationalToFloat(content.maxPrice) >= rationalToFloat(iassetPrice) &&
|
|
526
|
-
!isBuyOrderFullyRedeemed(utxo.assets, datum.orderType, iassetPrice),
|
|
527
|
-
)
|
|
528
|
-
.otherwise(() => false);
|
|
529
|
-
|
|
530
|
-
if (toHex(datum.iasset) !== toHex(iasset) || !isCorrectOrder) {
|
|
531
|
-
return O.none;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
// We constrained in the logic above that the ROB is a buy order and is not yet fully redeemed.
|
|
535
|
-
const collateralToSpend = robCollateralAmtToSpend(
|
|
536
|
-
utxo.assets,
|
|
537
|
-
datum.orderType,
|
|
538
|
-
);
|
|
539
|
-
|
|
540
|
-
return O.some(collateralToSpend);
|
|
541
|
-
}),
|
|
542
|
-
// From largest to smallest
|
|
543
|
-
A.sort(Ord.reverse(BigIntOrd)),
|
|
544
|
-
// We can fit only this number of redemptions with CDP open into a single Tx.
|
|
545
|
-
A.takeLeft(maxRobsInTx),
|
|
546
|
-
sum,
|
|
547
|
-
);
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
/**
|
|
551
|
-
* Pick random subset from all the ROBs (it does the necessary filtering) satisfying the target collateral to spend.
|
|
552
|
-
* It's relevant for BUY orders only.
|
|
553
|
-
*/
|
|
554
|
-
export function randomRobsSubsetSatisfyingTargetCollateral(
|
|
555
|
-
iasset: Uint8Array<ArrayBufferLike>,
|
|
556
|
-
collateralAsset: AssetClass,
|
|
557
|
-
targetCollateralToSpend: bigint,
|
|
558
|
-
iassetPrice: Rational,
|
|
559
|
-
allLrps: [UTxO, RobDatum][],
|
|
560
|
-
/**
|
|
561
|
-
* How many LRPs can be redeemed in a single Tx.
|
|
562
|
-
*/
|
|
563
|
-
maxLrpsInTx: number,
|
|
564
|
-
randomiseFn: (arr: [UTxO, RobDatum][]) => [UTxO, RobDatum][] = shuffle,
|
|
565
|
-
): [UTxO, RobDatum][] {
|
|
566
|
-
if (
|
|
567
|
-
targetCollateralToSpend <= 0n ||
|
|
568
|
-
iassetValueOfCollateral(targetCollateralToSpend, iassetPrice) <= 0n
|
|
569
|
-
) {
|
|
570
|
-
throw new Error('Must redeem and payout more than 0.');
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
const shuffled = randomiseFn(
|
|
574
|
-
F.pipe(
|
|
575
|
-
allLrps,
|
|
576
|
-
A.filter(
|
|
577
|
-
([utxo, datum]) =>
|
|
578
|
-
toHex(datum.iasset) === toHex(iasset) &&
|
|
579
|
-
match(datum.orderType)
|
|
580
|
-
.with(
|
|
581
|
-
{ BuyIAssetOrder: P.select() },
|
|
582
|
-
(content) =>
|
|
583
|
-
isSameAssetClass(collateralAsset, content.collateralAsset) &&
|
|
584
|
-
rationalToFloat(content.maxPrice) >=
|
|
585
|
-
rationalToFloat(iassetPrice),
|
|
586
|
-
)
|
|
587
|
-
// Only buy order types
|
|
588
|
-
.otherwise(() => false) &&
|
|
589
|
-
!isBuyOrderFullyRedeemed(utxo.assets, datum.orderType, iassetPrice),
|
|
590
|
-
),
|
|
591
|
-
),
|
|
592
|
-
);
|
|
593
|
-
|
|
594
|
-
// Sorted from highest to lowest by lovelaces to spend
|
|
595
|
-
let result: [UTxO, RobDatum][] = [];
|
|
596
|
-
let runningSum = 0n;
|
|
597
|
-
|
|
598
|
-
for (let i = 0; i < shuffled.length; i++) {
|
|
599
|
-
const element = shuffled[i];
|
|
600
|
-
|
|
601
|
-
const lovelacesToSpend = robCollateralAmtToSpend(
|
|
602
|
-
element[0].assets,
|
|
603
|
-
element[1].orderType,
|
|
604
|
-
);
|
|
605
|
-
|
|
606
|
-
const remainingToRedeem = targetCollateralToSpend - runningSum;
|
|
607
|
-
const remainingToPayout = iassetValueOfCollateral(
|
|
608
|
-
remainingToRedeem,
|
|
609
|
-
iassetPrice,
|
|
610
|
-
);
|
|
611
|
-
|
|
612
|
-
// When we can't add a new redemption because otherwise there would be no payout.
|
|
613
|
-
// Try to replace the smallest collected with a following larger one when available.
|
|
614
|
-
if (result.length > 0 && remainingToPayout <= 0n) {
|
|
615
|
-
const last = result[result.length - 1];
|
|
616
|
-
|
|
617
|
-
const lastSummary = robBuyOrderSummary(
|
|
618
|
-
last[0].assets,
|
|
619
|
-
last[1].orderType,
|
|
620
|
-
iassetPrice,
|
|
621
|
-
);
|
|
622
|
-
|
|
623
|
-
// Pop the smallest collected when the current is larger.
|
|
624
|
-
if (lastSummary.redeemableCollateral < lovelacesToSpend) {
|
|
625
|
-
result.pop()!;
|
|
626
|
-
runningSum -= lastSummary.redeemableCollateral;
|
|
627
|
-
} else {
|
|
628
|
-
continue;
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
result = insertSorted(
|
|
633
|
-
result,
|
|
634
|
-
element,
|
|
635
|
-
Ord.contramap<bigint, [UTxO, RobDatum]>(
|
|
636
|
-
([utxo, dat]) => robCollateralAmtToSpend(utxo.assets, dat.orderType),
|
|
637
|
-
// From highest to lowest
|
|
638
|
-
)(Ord.reverse(BigIntOrd)),
|
|
639
|
-
);
|
|
640
|
-
runningSum += lovelacesToSpend;
|
|
641
|
-
|
|
642
|
-
// When more items than max allowed, pop the one with smallest value
|
|
643
|
-
if (result.length > maxLrpsInTx) {
|
|
644
|
-
const popped = result.pop()!;
|
|
645
|
-
runningSum -= robCollateralAmtToSpend(
|
|
646
|
-
popped[0].assets,
|
|
647
|
-
popped[1].orderType,
|
|
648
|
-
);
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
if (runningSum >= targetCollateralToSpend) {
|
|
652
|
-
return result;
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
const remainingToSpend = targetCollateralToSpend - runningSum;
|
|
657
|
-
|
|
658
|
-
if (
|
|
659
|
-
remainingToSpend > 0n &&
|
|
660
|
-
iassetValueOfCollateral(remainingToSpend, iassetPrice) > 0n
|
|
661
|
-
) {
|
|
662
|
-
throw new Error("Couldn't achieve target lovelaces");
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
return result;
|
|
666
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { applyParamsToScript, SpendingValidator } from '@lucid-evolution/lucid';
|
|
2
|
-
import { castRobParams, RobParams } from './types';
|
|
3
|
-
import {
|
|
4
|
-
fromSystemParamsAssetLucid,
|
|
5
|
-
RobParamsSP,
|
|
6
|
-
} from '../../types/system-params';
|
|
7
|
-
import { _robValidator } from '../../validators/rob-validator';
|
|
8
|
-
|
|
9
|
-
export const mkRobValidator = (params: RobParams): SpendingValidator => {
|
|
10
|
-
return {
|
|
11
|
-
type: 'PlutusV3',
|
|
12
|
-
script: applyParamsToScript(_robValidator.cborHex, [castRobParams(params)]),
|
|
13
|
-
};
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export const mkRobValidatorFromSP = (
|
|
17
|
-
params: RobParamsSP,
|
|
18
|
-
): SpendingValidator => {
|
|
19
|
-
return {
|
|
20
|
-
type: 'PlutusV3',
|
|
21
|
-
script: applyParamsToScript(_robValidator.cborHex, [
|
|
22
|
-
castRobParams({
|
|
23
|
-
versionRecordToken: fromSystemParamsAssetLucid(
|
|
24
|
-
params.versionRecordToken,
|
|
25
|
-
),
|
|
26
|
-
iassetValHash: params.iassetValHash,
|
|
27
|
-
iassetAuthToken: fromSystemParamsAssetLucid(params.iassetAuthToken),
|
|
28
|
-
collateralAssetAuthToken: fromSystemParamsAssetLucid(
|
|
29
|
-
params.collateralAssetAuthToken,
|
|
30
|
-
),
|
|
31
|
-
iassetPolicyId: params.iassetPolicyId.unCurrencySymbol,
|
|
32
|
-
}),
|
|
33
|
-
]),
|
|
34
|
-
};
|
|
35
|
-
};
|