@renegade-fi/renegade-sdk 0.1.4 → 0.1.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/examples/malleable_external_match.ts +70 -26
- package/package.json +1 -1
- package/src/types/fixedPoint.ts +16 -1
- package/src/types/malleableMatch.ts +188 -11
- package/src/version.ts +2 -2
|
@@ -13,6 +13,7 @@ import type { ExternalOrder } from "../index";
|
|
|
13
13
|
import { http, createWalletClient } from "viem";
|
|
14
14
|
import { privateKeyToAccount } from "viem/accounts";
|
|
15
15
|
import { arbitrumSepolia } from "viem/chains";
|
|
16
|
+
import type { MalleableExternalMatchResponse } from "../src/types";
|
|
16
17
|
|
|
17
18
|
// Get API credentials from environment variables
|
|
18
19
|
const API_KEY = process.env.EXTERNAL_MATCH_KEY || "";
|
|
@@ -43,7 +44,6 @@ const walletClient = createWalletClient({
|
|
|
43
44
|
});
|
|
44
45
|
|
|
45
46
|
// Create the external match client
|
|
46
|
-
console.log("API KEY", API_KEY);
|
|
47
47
|
const client = ExternalMatchClient.newArbitrumSepoliaClient(API_KEY, API_SECRET);
|
|
48
48
|
|
|
49
49
|
// Example order for USDC/WETH pair
|
|
@@ -54,6 +54,71 @@ const order: ExternalOrder = {
|
|
|
54
54
|
quote_amount: BigInt(20_000_000), // 20 USDC
|
|
55
55
|
};
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Set a random base amount on the bundle and print the results
|
|
59
|
+
* @param bundle The malleable match bundle
|
|
60
|
+
*/
|
|
61
|
+
function setRandomBaseAmount(bundle: MalleableExternalMatchResponse) {
|
|
62
|
+
// Print bundle info
|
|
63
|
+
console.log("Bundle info:");
|
|
64
|
+
const [minBase, maxBase] = bundle.baseBounds();
|
|
65
|
+
console.log(`Base bounds: ${minBase} - ${maxBase}`);
|
|
66
|
+
|
|
67
|
+
// Pick a random base amount and see the send and receive amounts at that base amount
|
|
68
|
+
const dummyBaseAmount = randomInRange(minBase, maxBase);
|
|
69
|
+
const dummySendAmount = bundle.sendAmountAtBase(dummyBaseAmount);
|
|
70
|
+
const dummyReceiveAmount = bundle.receiveAmountAtBase(dummyBaseAmount);
|
|
71
|
+
console.log(`Hypothetical base amount: ${dummyBaseAmount}`);
|
|
72
|
+
console.log(`Hypothetical send amount: ${dummySendAmount}`);
|
|
73
|
+
console.log(`Hypothetical receive amount: ${dummyReceiveAmount}`);
|
|
74
|
+
|
|
75
|
+
// Pick an actual base amount to swap with
|
|
76
|
+
const swappedBaseAmount = randomInRange(minBase, maxBase);
|
|
77
|
+
|
|
78
|
+
// Setting the base amount will return the receive amount at the new base
|
|
79
|
+
// You can also call sendAmount and receiveAmount to get the amounts at the
|
|
80
|
+
// currently set base amount
|
|
81
|
+
bundle.setBaseAmount(swappedBaseAmount);
|
|
82
|
+
const send = bundle.sendAmount();
|
|
83
|
+
const recv = bundle.receiveAmount();
|
|
84
|
+
console.log(`Swapped base amount: ${swappedBaseAmount}`);
|
|
85
|
+
console.log(`Send amount: ${send}`);
|
|
86
|
+
console.log(`Receive amount: ${recv}`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Set a random quote amount on the bundle and print the results
|
|
91
|
+
* @param bundle The malleable match bundle
|
|
92
|
+
*/
|
|
93
|
+
// biome-ignore lint/correctness/noUnusedVariables: User can choose to use this function in the example
|
|
94
|
+
function setRandomQuoteAmount(bundle: MalleableExternalMatchResponse) {
|
|
95
|
+
// Print bundle info
|
|
96
|
+
console.log("Bundle info:");
|
|
97
|
+
const [minQuote, maxQuote] = bundle.quoteBounds();
|
|
98
|
+
console.log(`Quote bounds: ${minQuote} - ${maxQuote}`);
|
|
99
|
+
|
|
100
|
+
// Pick a random base amount and see the send and receive amounts at that base amount
|
|
101
|
+
const dummyQuoteAmount = randomInRange(minQuote, maxQuote);
|
|
102
|
+
const dummySendAmount = bundle.sendAmountAtQuote(dummyQuoteAmount);
|
|
103
|
+
const dummyReceiveAmount = bundle.receiveAmountAtQuote(dummyQuoteAmount);
|
|
104
|
+
console.log(`Hypothetical quote amount: ${dummyQuoteAmount}`);
|
|
105
|
+
console.log(`Hypothetical send amount: ${dummySendAmount}`);
|
|
106
|
+
console.log(`Hypothetical receive amount: ${dummyReceiveAmount}`);
|
|
107
|
+
|
|
108
|
+
// Pick an actual base amount to swap with
|
|
109
|
+
const swappedQuoteAmount = randomInRange(minQuote, maxQuote);
|
|
110
|
+
|
|
111
|
+
// Setting the quote amount will return the receive amount at the new quote
|
|
112
|
+
// You can also call sendAmount and receiveAmount to get the amounts at the
|
|
113
|
+
// currently set quote amount
|
|
114
|
+
bundle.setQuoteAmount(swappedQuoteAmount);
|
|
115
|
+
const send = bundle.sendAmount();
|
|
116
|
+
const recv = bundle.receiveAmount();
|
|
117
|
+
console.log(`Swapped quote amount: ${swappedQuoteAmount}`);
|
|
118
|
+
console.log(`Send amount: ${send}`);
|
|
119
|
+
console.log(`Receive amount: ${recv}`);
|
|
120
|
+
}
|
|
121
|
+
|
|
57
122
|
/**
|
|
58
123
|
* Submit a transaction to the chain
|
|
59
124
|
* @param settlementTx The settlement transaction
|
|
@@ -93,31 +158,10 @@ async function fullExample() {
|
|
|
93
158
|
return;
|
|
94
159
|
}
|
|
95
160
|
|
|
96
|
-
//
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
// Pick a random base amount and see the send and receive amounts at that base amount
|
|
102
|
-
const dummyBaseAmount = randomInRange(minBase, maxBase);
|
|
103
|
-
const dummySendAmount = bundle.sendAmountAtBase(dummyBaseAmount);
|
|
104
|
-
const dummyReceiveAmount = bundle.receiveAmountAtBase(dummyBaseAmount);
|
|
105
|
-
console.log(`Hypothetical base amount: ${dummyBaseAmount}`);
|
|
106
|
-
console.log(`Hypothetical send amount: ${dummySendAmount}`);
|
|
107
|
-
console.log(`Hypothetical receive amount: ${dummyReceiveAmount}`);
|
|
108
|
-
|
|
109
|
-
// Pick an actual base amount to swap with
|
|
110
|
-
const swappedBaseAmount = randomInRange(minBase, maxBase);
|
|
111
|
-
|
|
112
|
-
// Setting the base amount will return the receive amount at the new base
|
|
113
|
-
// You can also call sendAmount and receiveAmount to get the amounts at the
|
|
114
|
-
// currently set base amount
|
|
115
|
-
const _recv = bundle.setBaseAmount(swappedBaseAmount);
|
|
116
|
-
const send = bundle.sendAmount();
|
|
117
|
-
const recv = bundle.receiveAmount();
|
|
118
|
-
console.log(`Swapped base amount: ${swappedBaseAmount}`);
|
|
119
|
-
console.log(`Send amount: ${send}`);
|
|
120
|
-
console.log(`Receive amount: ${recv}`);
|
|
161
|
+
// Set a base amount on the bundle
|
|
162
|
+
// Alternatively, you can set a quote amount on the bundle - see
|
|
163
|
+
// `setRandomQuoteAmount`
|
|
164
|
+
setRandomBaseAmount(bundle);
|
|
121
165
|
|
|
122
166
|
// Step 3: Submit the transaction on-chain
|
|
123
167
|
const txHash = await submitTransaction(bundle.match_bundle.settlement_tx);
|
package/package.json
CHANGED
package/src/types/fixedPoint.ts
CHANGED
|
@@ -12,7 +12,7 @@ export class FixedPoint {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* Multiply a fixed point number by a
|
|
15
|
+
* Multiply a fixed point number by a bigint and return the floor
|
|
16
16
|
*/
|
|
17
17
|
floorMulInt(amount: bigint): bigint {
|
|
18
18
|
const product = this.value * amount;
|
|
@@ -20,4 +20,19 @@ export class FixedPoint {
|
|
|
20
20
|
const floored = product / FIXED_POINT_PRECISION_SHIFT;
|
|
21
21
|
return floored;
|
|
22
22
|
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Divide a bigint by a fixed point number and return the ceiling
|
|
26
|
+
*/
|
|
27
|
+
static ceilDivInt(amount: bigint, fp: FixedPoint): bigint {
|
|
28
|
+
const numerator = amount * FIXED_POINT_PRECISION_SHIFT;
|
|
29
|
+
const quotient = numerator / fp.value;
|
|
30
|
+
const remainder = numerator % fp.value;
|
|
31
|
+
|
|
32
|
+
if (remainder === BigInt(0)) {
|
|
33
|
+
return quotient;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return quotient + BigInt(1);
|
|
37
|
+
}
|
|
23
38
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { bytesToHex, concatBytes, hexToBytes, numberToBytes } from "viem/utils";
|
|
1
|
+
import { bytesToHex, concatBytes, hexToBytes, numberToBytes, numberToHex } from "viem/utils";
|
|
2
2
|
import { FixedPoint } from "./fixedPoint";
|
|
3
3
|
import {
|
|
4
4
|
type ApiExternalAssetTransfer,
|
|
@@ -8,10 +8,22 @@ import {
|
|
|
8
8
|
type SettlementTransaction,
|
|
9
9
|
} from "./index";
|
|
10
10
|
|
|
11
|
-
/** The
|
|
12
|
-
const
|
|
13
|
-
/**
|
|
14
|
-
|
|
11
|
+
/** The length of an amount in the calldata, which is 32 bytes for a `uint256` */
|
|
12
|
+
const AMOUNT_CALLDATA_LENGTH = 32;
|
|
13
|
+
/**
|
|
14
|
+
* The offset of the quote amount in the calldata,
|
|
15
|
+
* which is `4` because it's the first calldata argument
|
|
16
|
+
* after the 4-byte function selector
|
|
17
|
+
*/
|
|
18
|
+
const QUOTE_AMOUNT_OFFSET = 4;
|
|
19
|
+
/**
|
|
20
|
+
* The offset of the base amount in the calldata,
|
|
21
|
+
* which is `AMOUNT_CALLDATA_LENGTH` bytes after
|
|
22
|
+
* the quote amount as it is the next calldata argument
|
|
23
|
+
*/
|
|
24
|
+
const BASE_AMOUNT_OFFSET = QUOTE_AMOUNT_OFFSET + AMOUNT_CALLDATA_LENGTH;
|
|
25
|
+
/** The address used to represent the native asset */
|
|
26
|
+
const NATIVE_ASSET_ADDR = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
|
|
15
27
|
|
|
16
28
|
/**
|
|
17
29
|
* The response type for requesting a malleable quote on an external order
|
|
@@ -31,6 +43,17 @@ export class MalleableExternalMatchResponse {
|
|
|
31
43
|
* consistent
|
|
32
44
|
*/
|
|
33
45
|
base_amount?: bigint;
|
|
46
|
+
/**
|
|
47
|
+
* The quote amount chosen for the match
|
|
48
|
+
*
|
|
49
|
+
* If `undefined`, the quote amount hasn't been selected and defaults to the
|
|
50
|
+
* quote amount implied by the maximum base amount and the price in the match result.
|
|
51
|
+
*
|
|
52
|
+
* This field is not meant for client use directly, rather it is set by
|
|
53
|
+
* operating on the type and allows the response type to stay internally
|
|
54
|
+
* consistent
|
|
55
|
+
*/
|
|
56
|
+
quote_amount?: bigint;
|
|
34
57
|
/**
|
|
35
58
|
* Whether the match was sponsored
|
|
36
59
|
*/
|
|
@@ -45,11 +68,13 @@ export class MalleableExternalMatchResponse {
|
|
|
45
68
|
gas_sponsored: boolean,
|
|
46
69
|
gas_sponsorship_info?: GasSponsorshipInfo,
|
|
47
70
|
base_amount?: bigint,
|
|
71
|
+
quote_amount?: bigint,
|
|
48
72
|
) {
|
|
49
73
|
this.match_bundle = match_bundle;
|
|
50
74
|
this.gas_sponsored = gas_sponsored;
|
|
51
75
|
this.gas_sponsorship_info = gas_sponsorship_info;
|
|
52
76
|
this.base_amount = base_amount;
|
|
77
|
+
this.quote_amount = quote_amount;
|
|
53
78
|
}
|
|
54
79
|
|
|
55
80
|
/**
|
|
@@ -60,9 +85,15 @@ export class MalleableExternalMatchResponse {
|
|
|
60
85
|
public setBaseAmount(baseAmount: bigint) {
|
|
61
86
|
this.checkBaseAmount(baseAmount);
|
|
62
87
|
|
|
88
|
+
const impliedQuoteAmount = this.quoteAmount(baseAmount);
|
|
89
|
+
|
|
63
90
|
// Set the calldata
|
|
64
91
|
this.setBaseAmountCalldata(baseAmount);
|
|
92
|
+
this.setQuoteAmountCalldata(impliedQuoteAmount);
|
|
93
|
+
|
|
94
|
+
// Set the quote and base amounts on the response
|
|
65
95
|
this.base_amount = baseAmount;
|
|
96
|
+
this.quote_amount = impliedQuoteAmount;
|
|
66
97
|
|
|
67
98
|
return this.receiveAmount();
|
|
68
99
|
}
|
|
@@ -70,20 +101,75 @@ export class MalleableExternalMatchResponse {
|
|
|
70
101
|
/**
|
|
71
102
|
* Set the calldata to use a given base amount
|
|
72
103
|
*/
|
|
73
|
-
|
|
104
|
+
private setBaseAmountCalldata(baseAmount: bigint) {
|
|
74
105
|
const calldataBytes = hexToBytes(this.match_bundle.settlement_tx.data as `0x${string}`);
|
|
75
106
|
|
|
76
107
|
// Padded to 32 bytes
|
|
77
|
-
const baseAmountBytes = numberToBytes(baseAmount, { size:
|
|
108
|
+
const baseAmountBytes = numberToBytes(baseAmount, { size: AMOUNT_CALLDATA_LENGTH });
|
|
78
109
|
|
|
79
110
|
const prefix = calldataBytes.slice(0, BASE_AMOUNT_OFFSET);
|
|
80
111
|
const suffix = calldataBytes.slice(
|
|
81
|
-
BASE_AMOUNT_OFFSET +
|
|
112
|
+
BASE_AMOUNT_OFFSET + AMOUNT_CALLDATA_LENGTH,
|
|
82
113
|
calldataBytes.length,
|
|
83
114
|
);
|
|
84
115
|
|
|
116
|
+
// Set the calldata and the tx value
|
|
85
117
|
const newCalldataBytes = concatBytes([prefix, baseAmountBytes, suffix]);
|
|
86
118
|
const newCalladata = bytesToHex(newCalldataBytes);
|
|
119
|
+
const value = this.isNativeEthSell() ? baseAmount : 0n;
|
|
120
|
+
const valueHex = numberToHex(value);
|
|
121
|
+
|
|
122
|
+
const newMatchBundle = {
|
|
123
|
+
...this.match_bundle,
|
|
124
|
+
settlement_tx: {
|
|
125
|
+
...this.match_bundle.settlement_tx,
|
|
126
|
+
data: newCalladata,
|
|
127
|
+
value: valueHex,
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
this.match_bundle = newMatchBundle;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Set the `quote_amount` of the `match_result`
|
|
136
|
+
*
|
|
137
|
+
* @returns The amount received at the given `quote_amount`
|
|
138
|
+
*/
|
|
139
|
+
public setQuoteAmount(quoteAmount: bigint) {
|
|
140
|
+
const impliedBaseAmount = this.baseAmount(quoteAmount);
|
|
141
|
+
this.checkQuoteAmount(quoteAmount, impliedBaseAmount);
|
|
142
|
+
|
|
143
|
+
// Set the calldata
|
|
144
|
+
this.setQuoteAmountCalldata(quoteAmount);
|
|
145
|
+
this.setBaseAmountCalldata(impliedBaseAmount);
|
|
146
|
+
|
|
147
|
+
// Set the quote and base amounts on the response
|
|
148
|
+
this.quote_amount = quoteAmount;
|
|
149
|
+
this.base_amount = impliedBaseAmount;
|
|
150
|
+
|
|
151
|
+
return this.receiveAmount();
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Set the calldata to use a given quote amount
|
|
156
|
+
*/
|
|
157
|
+
private setQuoteAmountCalldata(quoteAmount: bigint) {
|
|
158
|
+
const calldataBytes = hexToBytes(this.match_bundle.settlement_tx.data as `0x${string}`);
|
|
159
|
+
|
|
160
|
+
// Padded to 32 bytes
|
|
161
|
+
const quoteAmountBytes = numberToBytes(quoteAmount, { size: AMOUNT_CALLDATA_LENGTH });
|
|
162
|
+
|
|
163
|
+
const prefix = calldataBytes.slice(0, QUOTE_AMOUNT_OFFSET);
|
|
164
|
+
const suffix = calldataBytes.slice(
|
|
165
|
+
QUOTE_AMOUNT_OFFSET + AMOUNT_CALLDATA_LENGTH,
|
|
166
|
+
calldataBytes.length,
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
// Set the calldata and the tx value
|
|
170
|
+
const newCalldataBytes = concatBytes([prefix, quoteAmountBytes, suffix]);
|
|
171
|
+
const newCalladata = bytesToHex(newCalldataBytes);
|
|
172
|
+
|
|
87
173
|
const newMatchBundle = {
|
|
88
174
|
...this.match_bundle,
|
|
89
175
|
settlement_tx: {
|
|
@@ -107,6 +193,41 @@ export class MalleableExternalMatchResponse {
|
|
|
107
193
|
];
|
|
108
194
|
}
|
|
109
195
|
|
|
196
|
+
/**
|
|
197
|
+
* Get the bounds on the quote amount
|
|
198
|
+
*
|
|
199
|
+
* Returns an array [min, max] inclusive
|
|
200
|
+
*/
|
|
201
|
+
public quoteBounds(): [bigint, bigint] {
|
|
202
|
+
const [minBase, maxBase] = this.baseBounds();
|
|
203
|
+
const price = this.getPriceFp();
|
|
204
|
+
|
|
205
|
+
const minQuote = price.floorMulInt(minBase);
|
|
206
|
+
const maxQuote = price.floorMulInt(maxBase);
|
|
207
|
+
|
|
208
|
+
return [minQuote, maxQuote];
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Get the bounds on the quote amount for a given base amount.
|
|
213
|
+
*
|
|
214
|
+
* For an explanation of these bounds, see:
|
|
215
|
+
* https://github.com/renegade-fi/renegade-contracts/blob/main/contracts-common/src/types/match.rs#L144-L174
|
|
216
|
+
*/
|
|
217
|
+
public quoteBoundsForBase(baseAmount: bigint): [bigint, bigint] {
|
|
218
|
+
const [minQuote, maxQuote] = this.quoteBounds();
|
|
219
|
+
|
|
220
|
+
const price = this.getPriceFp();
|
|
221
|
+
const refQuote = price.floorMulInt(baseAmount);
|
|
222
|
+
|
|
223
|
+
const direction = this.match_bundle.match_result.direction;
|
|
224
|
+
|
|
225
|
+
const resolvedMinQuote = direction === OrderSide.BUY ? refQuote : minQuote;
|
|
226
|
+
const resolvedMaxQuote = direction === OrderSide.BUY ? maxQuote : refQuote;
|
|
227
|
+
|
|
228
|
+
return [resolvedMinQuote, resolvedMaxQuote];
|
|
229
|
+
}
|
|
230
|
+
|
|
110
231
|
/**
|
|
111
232
|
* Get the receive amount at the currently set base amount
|
|
112
233
|
*/
|
|
@@ -121,6 +242,14 @@ export class MalleableExternalMatchResponse {
|
|
|
121
242
|
return this.computeReceiveAmount(baseAmount);
|
|
122
243
|
}
|
|
123
244
|
|
|
245
|
+
/**
|
|
246
|
+
* Get the receive amount at the given quote amount
|
|
247
|
+
*/
|
|
248
|
+
public receiveAmountAtQuote(quoteAmount: bigint) {
|
|
249
|
+
const baseAmount = this.baseAmount(quoteAmount);
|
|
250
|
+
return this.computeReceiveAmount(baseAmount);
|
|
251
|
+
}
|
|
252
|
+
|
|
124
253
|
/**
|
|
125
254
|
* Get the send amount at the currently set base amount
|
|
126
255
|
*/
|
|
@@ -135,18 +264,54 @@ export class MalleableExternalMatchResponse {
|
|
|
135
264
|
return this.computeSendAmount(baseAmount);
|
|
136
265
|
}
|
|
137
266
|
|
|
267
|
+
/**
|
|
268
|
+
* Get the send amount at the given quote amount
|
|
269
|
+
*/
|
|
270
|
+
public sendAmountAtQuote(quoteAmount: bigint) {
|
|
271
|
+
const baseAmount = this.baseAmount(quoteAmount);
|
|
272
|
+
return this.computeSendAmount(baseAmount);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Return whether the trade is a native ETH sell
|
|
277
|
+
*/
|
|
278
|
+
public isNativeEthSell(): boolean {
|
|
279
|
+
const matchRes = this.match_bundle.match_result;
|
|
280
|
+
const isSell = matchRes.direction === OrderSide.SELL;
|
|
281
|
+
const isBaseEth = matchRes.base_mint.toLowerCase() === NATIVE_ASSET_ADDR.toLowerCase();
|
|
282
|
+
|
|
283
|
+
return isBaseEth && isSell;
|
|
284
|
+
}
|
|
285
|
+
|
|
138
286
|
/**
|
|
139
287
|
* Check a base amount is in the valid range
|
|
140
288
|
*/
|
|
141
289
|
private checkBaseAmount(baseAmount: bigint) {
|
|
142
|
-
const min = this.
|
|
143
|
-
const max = this.match_bundle.match_result.max_base_amount;
|
|
290
|
+
const [min, max] = this.baseBounds();
|
|
144
291
|
|
|
145
292
|
if (baseAmount < min || baseAmount > max) {
|
|
146
293
|
throw new Error(`Base amount ${baseAmount} is not in the valid range ${min} - ${max}`);
|
|
147
294
|
}
|
|
148
295
|
}
|
|
149
296
|
|
|
297
|
+
/**
|
|
298
|
+
* Check a quote amount is in the valid range for a given base amount.
|
|
299
|
+
*
|
|
300
|
+
* This is true if the quote amount is within the bounds implied by the min
|
|
301
|
+
* and max base amounts given the price in the match results, and the
|
|
302
|
+
* quote amount does not imply a price improvement over the price in
|
|
303
|
+
* the match result.
|
|
304
|
+
*/
|
|
305
|
+
private checkQuoteAmount(quoteAmount: bigint, baseAmount: bigint) {
|
|
306
|
+
const [min, max] = this.quoteBoundsForBase(baseAmount);
|
|
307
|
+
|
|
308
|
+
if (quoteAmount < min || quoteAmount > max) {
|
|
309
|
+
throw new Error(
|
|
310
|
+
`Quote amount ${quoteAmount} is not in the valid range ${min} - ${max}`,
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
150
315
|
/**
|
|
151
316
|
* Get the current receive amount at the given base amount
|
|
152
317
|
*
|
|
@@ -183,11 +348,19 @@ export class MalleableExternalMatchResponse {
|
|
|
183
348
|
return baseAmount;
|
|
184
349
|
}
|
|
185
350
|
|
|
351
|
+
/**
|
|
352
|
+
* Get the base amount at the given quote amount
|
|
353
|
+
*/
|
|
354
|
+
private baseAmount(quoteAmount: bigint) {
|
|
355
|
+
const price = this.getPriceFp();
|
|
356
|
+
return FixedPoint.ceilDivInt(quoteAmount, price);
|
|
357
|
+
}
|
|
358
|
+
|
|
186
359
|
/**
|
|
187
360
|
* Get the quote amount at the given base amount
|
|
188
361
|
*/
|
|
189
362
|
private quoteAmount(baseAmount: bigint) {
|
|
190
|
-
const price =
|
|
363
|
+
const price = this.getPriceFp();
|
|
191
364
|
return price.floorMulInt(baseAmount);
|
|
192
365
|
}
|
|
193
366
|
|
|
@@ -200,6 +373,10 @@ export class MalleableExternalMatchResponse {
|
|
|
200
373
|
}
|
|
201
374
|
return this.base_amount;
|
|
202
375
|
}
|
|
376
|
+
|
|
377
|
+
private getPriceFp() {
|
|
378
|
+
return new FixedPoint(BigInt(this.match_bundle.match_result.price_fp));
|
|
379
|
+
}
|
|
203
380
|
}
|
|
204
381
|
|
|
205
382
|
/**
|
package/src/version.ts
CHANGED