@shapeshiftoss/swapper 19.0.0 → 20.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/exactOutputFiltering.test.d.ts +1 -0
- package/dist/cjs/exactOutputFiltering.test.js +70 -0
- package/dist/cjs/swapper.d.ts +3 -3
- package/dist/cjs/swapper.js +29 -6
- package/dist/cjs/swappers/AcrossSwapper/utils/getAcrossStepData.d.ts +1 -0
- package/dist/cjs/swappers/AcrossSwapper/utils/getAcrossStepData.js +2 -2
- package/dist/cjs/swappers/AcrossSwapper/utils/getAcrossTradeContext.js +1 -0
- package/dist/cjs/swappers/BebopSwapper/utils/getBebopStepData.d.ts +1 -0
- package/dist/cjs/swappers/BebopSwapper/utils/getBebopStepData.js +2 -2
- package/dist/cjs/swappers/BebopSwapper/utils/getBebopTradeContext.js +1 -0
- package/dist/cjs/swappers/DebridgeSwapper/utils/getDebridgeStepData.d.ts +1 -0
- package/dist/cjs/swappers/DebridgeSwapper/utils/getDebridgeStepData.js +2 -2
- package/dist/cjs/swappers/DebridgeSwapper/utils/getDebridgeTradeContext.js +1 -0
- package/dist/cjs/swappers/NearIntentsSwapper/endpoints.js +2 -0
- package/dist/cjs/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.d.ts +2 -1
- package/dist/cjs/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.js +14 -9
- package/dist/cjs/swappers/NearIntentsSwapper/swapperApi/getTradeRate.d.ts +2 -1
- package/dist/cjs/swappers/NearIntentsSwapper/swapperApi/getTradeRate.js +14 -9
- package/dist/cjs/swappers/NearIntentsSwapper/types.d.ts +3 -1
- package/dist/cjs/swappers/NearIntentsSwapper/utils/exactOutput.test.d.ts +1 -0
- package/dist/cjs/swappers/NearIntentsSwapper/utils/exactOutput.test.js +61 -0
- package/dist/cjs/swappers/NearIntentsSwapper/utils/getNearIntentsTradeContext.d.ts +2 -2
- package/dist/cjs/swappers/NearIntentsSwapper/utils/getNearIntentsTradeContext.js +4 -2
- package/dist/cjs/swappers/NearIntentsSwapper/utils/helpers.d.ts +3 -3
- package/dist/cjs/swappers/NearIntentsSwapper/utils/helpers.js +27 -23
- package/dist/cjs/swappers/PortalsSwapper/utils/getPortalsStepData.d.ts +1 -0
- package/dist/cjs/swappers/PortalsSwapper/utils/getPortalsStepData.js +3 -3
- package/dist/cjs/swappers/PortalsSwapper/utils/getPortalsTradeContext.d.ts +1 -0
- package/dist/cjs/swappers/PortalsSwapper/utils/getPortalsTradeContext.js +7 -1
- package/dist/cjs/swappers/RelaySwapper/endpoints.js +6 -0
- package/dist/cjs/swappers/RelaySwapper/getTradeQuote/getTradeQuote.d.ts +2 -1
- package/dist/cjs/swappers/RelaySwapper/getTradeQuote/getTradeQuote.js +5 -2
- package/dist/cjs/swappers/RelaySwapper/getTradeRate/getTradeRate.d.ts +2 -1
- package/dist/cjs/swappers/RelaySwapper/getTradeRate/getTradeRate.js +5 -2
- package/dist/cjs/swappers/RelaySwapper/utils/getRelayTradeContext.d.ts +2 -2
- package/dist/cjs/swappers/RelaySwapper/utils/getRelayTradeContext.js +22 -10
- package/dist/cjs/swappers/RelaySwapper/utils/helpers.d.ts +2 -2
- package/dist/cjs/swappers/RelaySwapper/utils/types.d.ts +4 -1
- package/dist/cjs/swappers/SunioSwapper/utils/getSunioStepData.d.ts +1 -0
- package/dist/cjs/swappers/SunioSwapper/utils/getSunioStepData.js +2 -2
- package/dist/cjs/swappers/SunioSwapper/utils/getSunioTradeContext.js +6 -1
- package/dist/cjs/types.d.ts +19 -2
- package/dist/cjs/types.js +2 -0
- package/dist/cjs/utils/helpers.d.ts +6 -0
- package/dist/cjs/utils/helpers.js +5 -1
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/exactOutputFiltering.test.d.ts +1 -0
- package/dist/esm/exactOutputFiltering.test.js +68 -0
- package/dist/esm/swapper.d.ts +3 -3
- package/dist/esm/swapper.js +29 -6
- package/dist/esm/swappers/AcrossSwapper/utils/getAcrossStepData.d.ts +1 -0
- package/dist/esm/swappers/AcrossSwapper/utils/getAcrossStepData.js +2 -2
- package/dist/esm/swappers/AcrossSwapper/utils/getAcrossTradeContext.js +1 -0
- package/dist/esm/swappers/BebopSwapper/utils/getBebopStepData.d.ts +1 -0
- package/dist/esm/swappers/BebopSwapper/utils/getBebopStepData.js +2 -2
- package/dist/esm/swappers/BebopSwapper/utils/getBebopTradeContext.js +1 -0
- package/dist/esm/swappers/DebridgeSwapper/utils/getDebridgeStepData.d.ts +1 -0
- package/dist/esm/swappers/DebridgeSwapper/utils/getDebridgeStepData.js +2 -2
- package/dist/esm/swappers/DebridgeSwapper/utils/getDebridgeTradeContext.js +1 -0
- package/dist/esm/swappers/NearIntentsSwapper/endpoints.js +4 -2
- package/dist/esm/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.d.ts +2 -1
- package/dist/esm/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.js +7 -3
- package/dist/esm/swappers/NearIntentsSwapper/swapperApi/getTradeRate.d.ts +2 -1
- package/dist/esm/swappers/NearIntentsSwapper/swapperApi/getTradeRate.js +7 -3
- package/dist/esm/swappers/NearIntentsSwapper/types.d.ts +3 -1
- package/dist/esm/swappers/NearIntentsSwapper/utils/exactOutput.test.d.ts +1 -0
- package/dist/esm/swappers/NearIntentsSwapper/utils/exactOutput.test.js +59 -0
- package/dist/esm/swappers/NearIntentsSwapper/utils/getNearIntentsTradeContext.d.ts +2 -2
- package/dist/esm/swappers/NearIntentsSwapper/utils/getNearIntentsTradeContext.js +4 -2
- package/dist/esm/swappers/NearIntentsSwapper/utils/helpers.d.ts +3 -3
- package/dist/esm/swappers/NearIntentsSwapper/utils/helpers.js +27 -23
- package/dist/esm/swappers/PortalsSwapper/utils/getPortalsStepData.d.ts +1 -0
- package/dist/esm/swappers/PortalsSwapper/utils/getPortalsStepData.js +3 -3
- package/dist/esm/swappers/PortalsSwapper/utils/getPortalsTradeContext.d.ts +1 -0
- package/dist/esm/swappers/PortalsSwapper/utils/getPortalsTradeContext.js +7 -1
- package/dist/esm/swappers/RelaySwapper/endpoints.js +8 -2
- package/dist/esm/swappers/RelaySwapper/getTradeQuote/getTradeQuote.d.ts +2 -1
- package/dist/esm/swappers/RelaySwapper/getTradeQuote/getTradeQuote.js +3 -1
- package/dist/esm/swappers/RelaySwapper/getTradeRate/getTradeRate.d.ts +2 -1
- package/dist/esm/swappers/RelaySwapper/getTradeRate/getTradeRate.js +3 -1
- package/dist/esm/swappers/RelaySwapper/utils/getRelayTradeContext.d.ts +2 -2
- package/dist/esm/swappers/RelaySwapper/utils/getRelayTradeContext.js +23 -11
- package/dist/esm/swappers/RelaySwapper/utils/helpers.d.ts +2 -2
- package/dist/esm/swappers/RelaySwapper/utils/types.d.ts +4 -1
- package/dist/esm/swappers/SunioSwapper/utils/getSunioStepData.d.ts +1 -0
- package/dist/esm/swappers/SunioSwapper/utils/getSunioStepData.js +2 -2
- package/dist/esm/swappers/SunioSwapper/utils/getSunioTradeContext.js +6 -1
- package/dist/esm/types.d.ts +19 -2
- package/dist/esm/types.js +2 -0
- package/dist/esm/utils/helpers.d.ts +6 -0
- package/dist/esm/utils/helpers.js +3 -0
- package/package.json +5 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { swappers } from './constants.js';
|
|
3
|
+
import { getTradeQuotes, getTradeRates } from './swapper.js';
|
|
4
|
+
import { SwapperName, TradeQuoteError } from './types.js';
|
|
5
|
+
import { BTC, ETH } from './utils/test-data/assets.js';
|
|
6
|
+
// Exact-output support is structural - a swapper cannot claim it without implementing it
|
|
7
|
+
describe('exact output capability', () => {
|
|
8
|
+
it('is implemented by the swappers whose upstream API can honour an exact buy amount', () => {
|
|
9
|
+
for (const swapperName of [SwapperName.NearIntents, SwapperName.Relay]) {
|
|
10
|
+
expect(swappers[swapperName]?.getExactOutputTradeRate).toBeDefined();
|
|
11
|
+
expect(swappers[swapperName]?.getExactOutputTradeQuote).toBeDefined();
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
it('is absent everywhere else', () => {
|
|
15
|
+
const exactOutputCapable = Object.values(SwapperName).filter(swapperName => swappers[swapperName]?.getExactOutputTradeRate !== undefined);
|
|
16
|
+
expect(exactOutputCapable).toEqual([SwapperName.Relay, SwapperName.NearIntents]);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
const exactOutputInput = {
|
|
20
|
+
sellAsset: ETH,
|
|
21
|
+
buyAsset: BTC,
|
|
22
|
+
buyAmountCryptoBaseUnit: '100000',
|
|
23
|
+
affiliateBps: '0',
|
|
24
|
+
allowMultiHop: true,
|
|
25
|
+
receiveAddress: undefined,
|
|
26
|
+
accountNumber: undefined,
|
|
27
|
+
quoteOrRate: 'rate',
|
|
28
|
+
};
|
|
29
|
+
const deps = {};
|
|
30
|
+
describe('getTradeRates on an exact buy amount', () => {
|
|
31
|
+
// Silently omitting these would read as the swapper being unavailable rather than unable
|
|
32
|
+
it('reports an error for a swapper that cannot quote one', async () => {
|
|
33
|
+
const result = await getTradeRates(exactOutputInput, SwapperName.Thorchain, deps);
|
|
34
|
+
expect(result).toBeDefined();
|
|
35
|
+
expect(result?.isErr()).toBe(true);
|
|
36
|
+
expect(result?.unwrapErr().code).toEqual(TradeQuoteError.ExactOutputNotSupported);
|
|
37
|
+
expect(result?.swapperName).toEqual(SwapperName.Thorchain);
|
|
38
|
+
});
|
|
39
|
+
it('skips entirely on a zero buy amount', async () => {
|
|
40
|
+
const result = await getTradeRates({ ...exactOutputInput, buyAmountCryptoBaseUnit: '0' }, SwapperName.Thorchain, deps);
|
|
41
|
+
expect(result).toBeUndefined();
|
|
42
|
+
});
|
|
43
|
+
// The base-unit regex upstream admits padded zeros, so the check can't be a string comparison
|
|
44
|
+
it('skips entirely on a padded zero buy amount', async () => {
|
|
45
|
+
const result = await getTradeRates({ ...exactOutputInput, buyAmountCryptoBaseUnit: '00' }, SwapperName.Thorchain, deps);
|
|
46
|
+
expect(result).toBeUndefined();
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
// Quotes dispatch on the same input shape as rates, so they gate the same way
|
|
50
|
+
describe('getTradeQuotes on an exact buy amount', () => {
|
|
51
|
+
const exactOutputQuoteInput = {
|
|
52
|
+
...exactOutputInput,
|
|
53
|
+
receiveAddress: 'bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq',
|
|
54
|
+
accountNumber: 0,
|
|
55
|
+
quoteOrRate: 'quote',
|
|
56
|
+
};
|
|
57
|
+
it('reports an error for a swapper that cannot quote one', async () => {
|
|
58
|
+
const result = await getTradeQuotes(exactOutputQuoteInput, SwapperName.Thorchain, deps);
|
|
59
|
+
expect(result).toBeDefined();
|
|
60
|
+
expect(result?.isErr()).toBe(true);
|
|
61
|
+
expect(result?.unwrapErr().code).toEqual(TradeQuoteError.ExactOutputNotSupported);
|
|
62
|
+
expect(result?.swapperName).toEqual(SwapperName.Thorchain);
|
|
63
|
+
});
|
|
64
|
+
it('skips entirely on a zero buy amount', async () => {
|
|
65
|
+
const result = await getTradeQuotes({ ...exactOutputQuoteInput, buyAmountCryptoBaseUnit: '0' }, SwapperName.Thorchain, deps);
|
|
66
|
+
expect(result).toBeUndefined();
|
|
67
|
+
});
|
|
68
|
+
});
|
package/dist/esm/swapper.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { GetTradeQuoteInput, GetTradeRateInput, QuoteResult, RateResult, SwapperDeps, SwapperName } from './types.js';
|
|
2
|
-
export declare const getTradeQuotes: (getTradeQuoteInput: GetTradeQuoteInput, swapperName: SwapperName, deps: SwapperDeps) => Promise<QuoteResult | undefined>;
|
|
3
|
-
export declare const getTradeRates: (getTradeRateInput: GetTradeRateInput, swapperName: SwapperName, deps: SwapperDeps, quoteTimeoutMs?: number) => Promise<RateResult | undefined>;
|
|
1
|
+
import type { GetExactOutputTradeQuoteInput, GetExactOutputTradeRateInput, GetTradeQuoteInput, GetTradeRateInput, QuoteResult, RateResult, SwapperDeps, SwapperName } from './types.js';
|
|
2
|
+
export declare const getTradeQuotes: (getTradeQuoteInput: GetTradeQuoteInput | GetExactOutputTradeQuoteInput, swapperName: SwapperName, deps: SwapperDeps) => Promise<QuoteResult | undefined>;
|
|
3
|
+
export declare const getTradeRates: (getTradeRateInput: GetTradeRateInput | GetExactOutputTradeRateInput, swapperName: SwapperName, deps: SwapperDeps, quoteTimeoutMs?: number) => Promise<RateResult | undefined>;
|
package/dist/esm/swapper.js
CHANGED
|
@@ -1,17 +1,31 @@
|
|
|
1
1
|
import { bnOrZero, timeoutMonadic, timeoutMonadicWithOriginal } from '@shapeshiftoss/utils';
|
|
2
|
+
import { Err } from '@sniptt/monads';
|
|
2
3
|
import { QUOTE_TIMEOUT_ERROR, QUOTE_TIMEOUT_MS, swappers } from './constants.js';
|
|
3
4
|
import { TradeQuoteError } from './types.js';
|
|
4
5
|
import { makeSwapErrorRight } from './utils/index.js';
|
|
6
|
+
const EXACT_OUTPUT_NOT_SUPPORTED_ERROR = makeSwapErrorRight({
|
|
7
|
+
code: TradeQuoteError.ExactOutputNotSupported,
|
|
8
|
+
message: 'This swapper cannot derive a sell amount from an exact buy amount',
|
|
9
|
+
});
|
|
5
10
|
export const getTradeQuotes = async (getTradeQuoteInput, swapperName, deps) => {
|
|
6
11
|
if (bnOrZero(getTradeQuoteInput.affiliateBps).lt(0))
|
|
7
12
|
return;
|
|
8
|
-
if (getTradeQuoteInput.sellAmountIncludingProtocolFeesCryptoBaseUnit === '0')
|
|
9
|
-
return;
|
|
10
13
|
const swapper = swappers[swapperName];
|
|
11
14
|
if (swapper === undefined)
|
|
12
15
|
return;
|
|
16
|
+
// Compared numerically so a padded zero can't slip through as an amount
|
|
17
|
+
const drivingAmount = 'buyAmountCryptoBaseUnit' in getTradeQuoteInput
|
|
18
|
+
? getTradeQuoteInput.buyAmountCryptoBaseUnit
|
|
19
|
+
: getTradeQuoteInput.sellAmountIncludingProtocolFeesCryptoBaseUnit;
|
|
20
|
+
if (bnOrZero(drivingAmount).isZero())
|
|
21
|
+
return;
|
|
22
|
+
const quotePromise = 'buyAmountCryptoBaseUnit' in getTradeQuoteInput
|
|
23
|
+
? swapper.getExactOutputTradeQuote?.(getTradeQuoteInput, deps)
|
|
24
|
+
: swapper.getTradeQuote(getTradeQuoteInput, deps);
|
|
25
|
+
if (!quotePromise)
|
|
26
|
+
return { ...Err(EXACT_OUTPUT_NOT_SUPPORTED_ERROR), swapperName };
|
|
13
27
|
try {
|
|
14
|
-
const quote = await timeoutMonadic(
|
|
28
|
+
const quote = await timeoutMonadic(quotePromise, QUOTE_TIMEOUT_MS, QUOTE_TIMEOUT_ERROR);
|
|
15
29
|
return {
|
|
16
30
|
...quote,
|
|
17
31
|
swapperName,
|
|
@@ -26,13 +40,22 @@ export const getTradeQuotes = async (getTradeQuoteInput, swapperName, deps) => {
|
|
|
26
40
|
export const getTradeRates = async (getTradeRateInput, swapperName, deps, quoteTimeoutMs = QUOTE_TIMEOUT_MS) => {
|
|
27
41
|
if (bnOrZero(getTradeRateInput.affiliateBps).lt(0))
|
|
28
42
|
return;
|
|
29
|
-
if (getTradeRateInput.sellAmountIncludingProtocolFeesCryptoBaseUnit === '0')
|
|
30
|
-
return;
|
|
31
43
|
const swapper = swappers[swapperName];
|
|
32
44
|
if (swapper === undefined)
|
|
33
45
|
return;
|
|
46
|
+
// Compared numerically so a padded zero can't slip through as an amount
|
|
47
|
+
const drivingAmount = 'buyAmountCryptoBaseUnit' in getTradeRateInput
|
|
48
|
+
? getTradeRateInput.buyAmountCryptoBaseUnit
|
|
49
|
+
: getTradeRateInput.sellAmountIncludingProtocolFeesCryptoBaseUnit;
|
|
50
|
+
if (bnOrZero(drivingAmount).isZero())
|
|
51
|
+
return;
|
|
52
|
+
const ratePromise = 'buyAmountCryptoBaseUnit' in getTradeRateInput
|
|
53
|
+
? swapper.getExactOutputTradeRate?.(getTradeRateInput, deps)
|
|
54
|
+
: swapper.getTradeRate(getTradeRateInput, deps);
|
|
55
|
+
if (!ratePromise)
|
|
56
|
+
return { ...Err(EXACT_OUTPUT_NOT_SUPPORTED_ERROR), swapperName };
|
|
34
57
|
try {
|
|
35
|
-
const { timed, original } = timeoutMonadicWithOriginal(
|
|
58
|
+
const { timed, original } = timeoutMonadicWithOriginal(ratePromise, quoteTimeoutMs, makeSwapErrorRight({
|
|
36
59
|
code: TradeQuoteError.Timeout,
|
|
37
60
|
message: `quote timed out after ${quoteTimeoutMs / 1000}s`,
|
|
38
61
|
}));
|
|
@@ -3,6 +3,7 @@ import type { StepDataArgs, SwapErrorRight, TxBuildData } from '../../../types.j
|
|
|
3
3
|
import type { AcrossSwapTx } from './types.js';
|
|
4
4
|
type BaseArgs = {
|
|
5
5
|
swapTx: AcrossSwapTx;
|
|
6
|
+
sellAmountCryptoBaseUnit: string;
|
|
6
7
|
spenderAddress: string;
|
|
7
8
|
fallbackNetworkFeeCryptoBaseUnit: string;
|
|
8
9
|
};
|
|
@@ -7,7 +7,7 @@ import { makeNetworkFeeEstimationFailedErr, makeSwapErrorRight, makeTradeStepBui
|
|
|
7
7
|
import { getEvmNetworkFeeCryptoBaseUnit } from '../../../utils/evm/index.js';
|
|
8
8
|
import { getSolanaNetworkFeeCryptoBaseUnit } from '../../../utils/solana/index.js';
|
|
9
9
|
export async function getAcrossStepData(args) {
|
|
10
|
-
const { swapTx, sellAsset, spenderAddress, from, type, input, fallbackNetworkFeeCryptoBaseUnit, deps, } = args;
|
|
10
|
+
const { swapTx, sellAsset, sellAmountCryptoBaseUnit, spenderAddress, from, type, input, fallbackNetworkFeeCryptoBaseUnit, deps, } = args;
|
|
11
11
|
const supportsEIP1559 = 'supportsEIP1559' in input ? input.supportsEIP1559 : false;
|
|
12
12
|
switch (swapTx.ecosystem) {
|
|
13
13
|
case 'evm': {
|
|
@@ -22,7 +22,7 @@ export async function getAcrossStepData(args) {
|
|
|
22
22
|
};
|
|
23
23
|
const stateOverride = {
|
|
24
24
|
sellAsset,
|
|
25
|
-
sellAmountCryptoBaseUnit
|
|
25
|
+
sellAmountCryptoBaseUnit,
|
|
26
26
|
spenderAddress,
|
|
27
27
|
};
|
|
28
28
|
if (type === 'rate') {
|
|
@@ -167,6 +167,7 @@ export const getAcrossTradeContext = async ({ input, deps, depositor, recipient,
|
|
|
167
167
|
stepDataArgs: {
|
|
168
168
|
swapTx: quote.swapTx,
|
|
169
169
|
sellAsset,
|
|
170
|
+
sellAmountCryptoBaseUnit: sellAmountIncludingProtocolFeesCryptoBaseUnit,
|
|
170
171
|
from: depositor,
|
|
171
172
|
spenderAddress: allowanceContract,
|
|
172
173
|
fallbackNetworkFeeCryptoBaseUnit: quote.fees.originGas.amount,
|
|
@@ -3,6 +3,7 @@ import type { StepDataArgs, SwapErrorRight, TxBuildData } from '../../../types.j
|
|
|
3
3
|
import type { BebopQuoteResponse } from '../types.js';
|
|
4
4
|
type BaseArgs = {
|
|
5
5
|
tx: BebopQuoteResponse['tx'];
|
|
6
|
+
sellAmountCryptoBaseUnit: string;
|
|
6
7
|
spenderAddress: string;
|
|
7
8
|
};
|
|
8
9
|
export type GetBebopStepDataArgs = StepDataArgs<BaseArgs, {
|
|
@@ -5,7 +5,7 @@ import { fromHex } from 'viem';
|
|
|
5
5
|
import { makeNetworkFeeEstimationFailedErr } from '../../../utils/index.js';
|
|
6
6
|
import { getEvmNetworkFeeCryptoBaseUnit } from '../../../utils/evm/index.js';
|
|
7
7
|
export async function getBebopStepData(args) {
|
|
8
|
-
const { tx, spenderAddress, sellAsset, type, input, from, deps } = args;
|
|
8
|
+
const { tx, spenderAddress, sellAsset, sellAmountCryptoBaseUnit, type, input, from, deps } = args;
|
|
9
9
|
const adapter = deps.assertGetEvmChainAdapter(sellAsset.chainId);
|
|
10
10
|
const supportsEIP1559 = 'supportsEIP1559' in input ? input.supportsEIP1559 : false;
|
|
11
11
|
if (type === 'rate') {
|
|
@@ -40,7 +40,7 @@ export async function getBebopStepData(args) {
|
|
|
40
40
|
supportsEIP1559,
|
|
41
41
|
stateOverride: {
|
|
42
42
|
sellAsset,
|
|
43
|
-
sellAmountCryptoBaseUnit
|
|
43
|
+
sellAmountCryptoBaseUnit,
|
|
44
44
|
spenderAddress,
|
|
45
45
|
},
|
|
46
46
|
});
|
|
@@ -3,6 +3,7 @@ import type { StepDataArgs, SwapErrorRight, TxBuildData } from '../../../types.j
|
|
|
3
3
|
import type { DebridgeTx } from './types.js';
|
|
4
4
|
type BaseArgs = {
|
|
5
5
|
tx: DebridgeTx;
|
|
6
|
+
sellAmountCryptoBaseUnit: string;
|
|
6
7
|
gasLimit: string | undefined;
|
|
7
8
|
spenderAddress: string;
|
|
8
9
|
fallbackNetworkFeeCryptoBaseUnit: string | undefined;
|
|
@@ -3,7 +3,7 @@ import { Err, Ok } from '@sniptt/monads';
|
|
|
3
3
|
import { makeNetworkFeeEstimationFailedErr } from '../../../utils/index.js';
|
|
4
4
|
import { getEvmNetworkFeeCryptoBaseUnit } from '../../../utils/evm/index.js';
|
|
5
5
|
export async function getDebridgeStepData(args) {
|
|
6
|
-
const { tx, gasLimit, spenderAddress, fallbackNetworkFeeCryptoBaseUnit, sellAsset, from, type, input, deps, } = args;
|
|
6
|
+
const { tx, sellAmountCryptoBaseUnit, gasLimit, spenderAddress, fallbackNetworkFeeCryptoBaseUnit, sellAsset, from, type, input, deps, } = args;
|
|
7
7
|
const adapter = deps.assertGetEvmChainAdapter(sellAsset.chainId);
|
|
8
8
|
const supportsEIP1559 = 'supportsEIP1559' in input ? input.supportsEIP1559 : false;
|
|
9
9
|
const transactionData = {
|
|
@@ -16,7 +16,7 @@ export async function getDebridgeStepData(args) {
|
|
|
16
16
|
};
|
|
17
17
|
const stateOverride = {
|
|
18
18
|
sellAsset,
|
|
19
|
-
sellAmountCryptoBaseUnit
|
|
19
|
+
sellAmountCryptoBaseUnit,
|
|
20
20
|
spenderAddress,
|
|
21
21
|
};
|
|
22
22
|
if (type === 'rate') {
|
|
@@ -81,6 +81,7 @@ export const getDebridgeTradeContext = async ({ input, deps, senderAddress, reci
|
|
|
81
81
|
protocolFees: quote.protocolFees,
|
|
82
82
|
stepDataArgs: {
|
|
83
83
|
tx: quote.tx,
|
|
84
|
+
sellAmountCryptoBaseUnit: sellAmountIncludingProtocolFeesCryptoBaseUnit,
|
|
84
85
|
gasLimit: quote.gasLimit,
|
|
85
86
|
fallbackNetworkFeeCryptoBaseUnit: quote.fallbackNetworkFeeCryptoBaseUnit,
|
|
86
87
|
sellAsset,
|
|
@@ -4,13 +4,15 @@ import { getEvmTransactionFees, getUnsignedEvmTransaction } from '../../utils/ev
|
|
|
4
4
|
import { getSolanaTransactionFees, getUnsignedSolanaTransaction } from '../../utils/solana/index.js';
|
|
5
5
|
import { getTronTransactionFees, getUnsignedTronTransaction } from '../../utils/tron/index.js';
|
|
6
6
|
import { getUnsignedUtxoTransaction, getUtxoTransactionFees } from '../../utils/utxo/index.js';
|
|
7
|
-
import { getTradeQuote } from './swapperApi/getTradeQuote.js';
|
|
8
|
-
import { getTradeRate } from './swapperApi/getTradeRate.js';
|
|
7
|
+
import { getExactOutputTradeQuote, getTradeQuote } from './swapperApi/getTradeQuote.js';
|
|
8
|
+
import { getExactOutputTradeRate, getTradeRate } from './swapperApi/getTradeRate.js';
|
|
9
9
|
import { getNearIntentsStatusMessage, mapNearIntentsStatus } from './utils/helpers.js';
|
|
10
10
|
import { initializeOneClickService, OneClickService } from './utils/oneClickService.js';
|
|
11
11
|
export const nearIntentsApi = {
|
|
12
12
|
getTradeQuote: (input, deps) => getTradeQuote(input, deps),
|
|
13
13
|
getTradeRate: (input, deps) => getTradeRate(input, deps),
|
|
14
|
+
getExactOutputTradeQuote: (input, deps) => getExactOutputTradeQuote(input, deps),
|
|
15
|
+
getExactOutputTradeRate: (input, deps) => getExactOutputTradeRate(input, deps),
|
|
14
16
|
getUnsignedEvmTransaction,
|
|
15
17
|
getEvmTransactionFees,
|
|
16
18
|
getUnsignedUtxoTransaction,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Result } from '@sniptt/monads';
|
|
2
2
|
import type { SwapErrorRight, SwapperDeps, TradeQuote } from '../../../types.js';
|
|
3
|
-
import type { NearIntentsTradeQuoteInput } from '../types.js';
|
|
3
|
+
import type { NearIntentsExactOutputTradeQuoteInput, NearIntentsTradeQuoteInput } from '../types.js';
|
|
4
4
|
export declare const getTradeQuote: (input: NearIntentsTradeQuoteInput, deps: SwapperDeps) => Promise<Result<TradeQuote[], SwapErrorRight>>;
|
|
5
|
+
export declare const getExactOutputTradeQuote: (input: NearIntentsExactOutputTradeQuoteInput, deps: SwapperDeps) => Promise<Result<TradeQuote[], SwapErrorRight>>;
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import { Err, Ok } from '@sniptt/monads';
|
|
2
2
|
import { assertQuoteAddresses } from '../../../utils/index.js';
|
|
3
|
+
import { getTradeAmount } from '../../../utils/helpers.js';
|
|
3
4
|
import { QuoteRequest } from '../types.js';
|
|
4
5
|
import { getNearIntentsStepData } from '../utils/getNearIntentsStepData.js';
|
|
5
6
|
import { getNearIntentsTradeContext } from '../utils/getNearIntentsTradeContext.js';
|
|
6
7
|
import { buildNearIntentsQuoteRequest, fetchNearIntentsQuote, getNearIntentsQuoteDeadline, resolveNearIntentsAssets, } from '../utils/helpers.js';
|
|
7
8
|
import { initializeOneClickService } from '../utils/oneClickService.js';
|
|
8
|
-
|
|
9
|
-
const { sellAsset, buyAsset, accountNumber, affiliateBps
|
|
9
|
+
const getQuote = async (input, deps) => {
|
|
10
|
+
const { sellAsset, buyAsset, accountNumber, affiliateBps } = input;
|
|
10
11
|
const addresses = assertQuoteAddresses(input);
|
|
11
12
|
if (addresses.isErr())
|
|
12
13
|
return Err(addresses.unwrapErr());
|
|
13
14
|
const { sendAddress, receiveAddress } = addresses.unwrap();
|
|
14
15
|
initializeOneClickService(deps.config.VITE_NEAR_INTENTS_API_KEY);
|
|
16
|
+
const amount = getTradeAmount(input);
|
|
15
17
|
const maybeAssets = await resolveNearIntentsAssets({ sellAsset, buyAsset });
|
|
16
18
|
if (maybeAssets.isErr())
|
|
17
19
|
return Err(maybeAssets.unwrapErr());
|
|
@@ -19,7 +21,7 @@ export const getTradeQuote = async (input, deps) => {
|
|
|
19
21
|
const quoteRequest = buildNearIntentsQuoteRequest({
|
|
20
22
|
originAsset,
|
|
21
23
|
destinationAsset,
|
|
22
|
-
|
|
24
|
+
amount,
|
|
23
25
|
slippageTolerancePercentageDecimal: input.slippageTolerancePercentageDecimal,
|
|
24
26
|
affiliateBps,
|
|
25
27
|
refundTo: sendAddress,
|
|
@@ -72,3 +74,5 @@ export const getTradeQuote = async (input, deps) => {
|
|
|
72
74
|
};
|
|
73
75
|
return Ok([tradeQuote]);
|
|
74
76
|
};
|
|
77
|
+
export const getTradeQuote = (input, deps) => getQuote(input, deps);
|
|
78
|
+
export const getExactOutputTradeQuote = (input, deps) => getQuote(input, deps);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Result } from '@sniptt/monads';
|
|
2
2
|
import type { SwapErrorRight, SwapperDeps, TradeRate } from '../../../types.js';
|
|
3
|
-
import type { NearIntentsTradeRateInput } from '../types.js';
|
|
3
|
+
import type { NearIntentsExactOutputTradeRateInput, NearIntentsTradeRateInput } from '../types.js';
|
|
4
4
|
export declare const getTradeRate: (input: NearIntentsTradeRateInput, deps: SwapperDeps) => Promise<Result<TradeRate[], SwapErrorRight>>;
|
|
5
|
+
export declare const getExactOutputTradeRate: (input: NearIntentsExactOutputTradeRateInput, deps: SwapperDeps) => Promise<Result<TradeRate[], SwapErrorRight>>;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { Err, Ok } from '@sniptt/monads';
|
|
2
|
+
import { getTradeAmount } from '../../../utils/helpers.js';
|
|
2
3
|
import { QuoteRequest } from '../types.js';
|
|
3
4
|
import { getNearIntentsStepData } from '../utils/getNearIntentsStepData.js';
|
|
4
5
|
import { getNearIntentsTradeContext } from '../utils/getNearIntentsTradeContext.js';
|
|
5
6
|
import { buildNearIntentsQuoteRequest, fetchNearIntentsQuote, getNearIntentsQuoteDeadline, resolveNearIntentsAssets, } from '../utils/helpers.js';
|
|
6
7
|
import { initializeOneClickService } from '../utils/oneClickService.js';
|
|
7
|
-
|
|
8
|
-
const { accountNumber, sellAsset, buyAsset, affiliateBps,
|
|
8
|
+
const getRate = async (input, deps) => {
|
|
9
|
+
const { accountNumber, sellAsset, buyAsset, affiliateBps, receiveAddress, sendAddress } = input;
|
|
9
10
|
initializeOneClickService(deps.config.VITE_NEAR_INTENTS_API_KEY);
|
|
11
|
+
const amount = getTradeAmount(input);
|
|
10
12
|
const maybeAssets = await resolveNearIntentsAssets({ sellAsset, buyAsset });
|
|
11
13
|
if (maybeAssets.isErr())
|
|
12
14
|
return Err(maybeAssets.unwrapErr());
|
|
@@ -14,7 +16,7 @@ export const getTradeRate = async (input, deps) => {
|
|
|
14
16
|
const quoteRequest = buildNearIntentsQuoteRequest({
|
|
15
17
|
originAsset,
|
|
16
18
|
destinationAsset,
|
|
17
|
-
|
|
19
|
+
amount,
|
|
18
20
|
slippageTolerancePercentageDecimal: input.slippageTolerancePercentageDecimal,
|
|
19
21
|
affiliateBps,
|
|
20
22
|
refundTo: sendAddress ?? 'check-price',
|
|
@@ -58,3 +60,5 @@ export const getTradeRate = async (input, deps) => {
|
|
|
58
60
|
};
|
|
59
61
|
return Ok([tradeRate]);
|
|
60
62
|
};
|
|
63
|
+
export const getTradeRate = (input, deps) => getRate(input, deps);
|
|
64
|
+
export const getExactOutputTradeRate = (input, deps) => getRate(input, deps);
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { KnownChainIds } from '@shapeshiftoss/types';
|
|
2
|
-
import type { GetEvmTradeQuoteInput, GetEvmTradeRateInput, GetNearTradeQuoteInput, GetNearTradeRateInput, GetSolanaTradeQuoteInput, GetSolanaTradeRateInput, GetStarknetTradeQuoteInput, GetStarknetTradeRateInput, GetSuiTradeQuoteInput, GetSuiTradeRateInput, GetTonTradeQuoteInput, GetTonTradeRateInput, GetTronTradeQuoteInput, GetTronTradeRateInput, GetUtxoTradeQuoteInput, GetUtxoTradeRateInput } from '../../types.js';
|
|
2
|
+
import type { GetEvmTradeQuoteInput, GetEvmTradeRateInput, GetNearTradeQuoteInput, GetNearTradeRateInput, GetSolanaTradeQuoteInput, GetSolanaTradeRateInput, GetStarknetTradeQuoteInput, GetStarknetTradeRateInput, GetSuiTradeQuoteInput, GetSuiTradeRateInput, GetTonTradeQuoteInput, GetTonTradeRateInput, GetTronTradeQuoteInput, GetTronTradeRateInput, GetUtxoTradeQuoteInput, GetUtxoTradeRateInput, WithExactBuyAmount } from '../../types.js';
|
|
3
3
|
export type NearIntentsTradeQuoteInput = GetEvmTradeQuoteInput | GetUtxoTradeQuoteInput | GetSolanaTradeQuoteInput | GetTronTradeQuoteInput | GetSuiTradeQuoteInput | GetStarknetTradeQuoteInput | GetNearTradeQuoteInput | GetTonTradeQuoteInput;
|
|
4
4
|
export type NearIntentsTradeRateInput = GetEvmTradeRateInput | GetUtxoTradeRateInput | GetSolanaTradeRateInput | GetTronTradeRateInput | GetSuiTradeRateInput | GetStarknetTradeRateInput | GetNearTradeRateInput | GetTonTradeRateInput;
|
|
5
|
+
export type NearIntentsExactOutputTradeQuoteInput = WithExactBuyAmount<NearIntentsTradeQuoteInput>;
|
|
6
|
+
export type NearIntentsExactOutputTradeRateInput = WithExactBuyAmount<NearIntentsTradeRateInput>;
|
|
5
7
|
export type NearIntentsMetadata = {
|
|
6
8
|
name: 'nearIntents';
|
|
7
9
|
depositAddress: string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { QuoteRequest } from '../types.js';
|
|
3
|
+
import { buildNearIntentsQuoteRequest } from './helpers.js';
|
|
4
|
+
const BASE_ARGS = {
|
|
5
|
+
originAsset: 'nep141:base-0x833589fcd6edb6e08f4c7c32d4f71b54bda02913.omft.near',
|
|
6
|
+
destinationAsset: 'nep141:btc.omft.near',
|
|
7
|
+
amount: { direction: 'exactIn', cryptoBaseUnit: '65000000' },
|
|
8
|
+
slippageTolerancePercentageDecimal: '0.01',
|
|
9
|
+
affiliateBps: '10',
|
|
10
|
+
refundTo: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
|
|
11
|
+
recipient: 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4',
|
|
12
|
+
refundType: QuoteRequest.refundType.ORIGIN_CHAIN,
|
|
13
|
+
recipientType: QuoteRequest.recipientType.DESTINATION_CHAIN,
|
|
14
|
+
deadline: '2026-08-10T23:59:00.000Z',
|
|
15
|
+
};
|
|
16
|
+
const EXACT_OUTPUT_AMOUNT = {
|
|
17
|
+
direction: 'exactOut',
|
|
18
|
+
cryptoBaseUnit: '100000',
|
|
19
|
+
};
|
|
20
|
+
describe('buildNearIntentsQuoteRequest', () => {
|
|
21
|
+
describe('exact input', () => {
|
|
22
|
+
it('requests EXACT_INPUT with the sell amount', () => {
|
|
23
|
+
const request = buildNearIntentsQuoteRequest(BASE_ARGS);
|
|
24
|
+
expect(request.swapType).toEqual(QuoteRequest.swapType.EXACT_INPUT);
|
|
25
|
+
expect(request.amount).toEqual('65000000');
|
|
26
|
+
});
|
|
27
|
+
it('passes the requested slippage through untouched', () => {
|
|
28
|
+
const request = buildNearIntentsQuoteRequest({
|
|
29
|
+
...BASE_ARGS,
|
|
30
|
+
slippageTolerancePercentageDecimal: '0',
|
|
31
|
+
});
|
|
32
|
+
expect(request.slippageTolerance).toEqual(0);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
describe('exact output', () => {
|
|
36
|
+
it('requests EXACT_OUTPUT with the buy amount', () => {
|
|
37
|
+
const request = buildNearIntentsQuoteRequest({ ...BASE_ARGS, amount: EXACT_OUTPUT_AMOUNT });
|
|
38
|
+
expect(request.swapType).toEqual(QuoteRequest.swapType.EXACT_OUTPUT);
|
|
39
|
+
expect(request.amount).toEqual('100000');
|
|
40
|
+
});
|
|
41
|
+
// A tighter band is the user's call - the failure mode is a refund, not a loss
|
|
42
|
+
it('passes a requested zero slippage through untouched, as exact input does', () => {
|
|
43
|
+
const request = buildNearIntentsQuoteRequest({
|
|
44
|
+
...BASE_ARGS,
|
|
45
|
+
amount: EXACT_OUTPUT_AMOUNT,
|
|
46
|
+
slippageTolerancePercentageDecimal: '0',
|
|
47
|
+
});
|
|
48
|
+
expect(request.slippageTolerance).toEqual(0);
|
|
49
|
+
});
|
|
50
|
+
it('honours a requested slippage', () => {
|
|
51
|
+
const request = buildNearIntentsQuoteRequest({
|
|
52
|
+
...BASE_ARGS,
|
|
53
|
+
amount: EXACT_OUTPUT_AMOUNT,
|
|
54
|
+
slippageTolerancePercentageDecimal: '0.05',
|
|
55
|
+
});
|
|
56
|
+
expect(request.slippageTolerance).toEqual(500);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Asset } from '@shapeshiftoss/types';
|
|
2
2
|
import type { Result } from '@sniptt/monads';
|
|
3
3
|
import type { QuoteFeeData, SwapErrorRight, SwapperDeps, TradeCommon, TradeStepCommon } from '../../../types.js';
|
|
4
|
-
import type { NearIntentsTradeQuoteInput, NearIntentsTradeRateInput, QuoteResponse } from '../types.js';
|
|
4
|
+
import type { NearIntentsExactOutputTradeQuoteInput, NearIntentsExactOutputTradeRateInput, NearIntentsTradeQuoteInput, NearIntentsTradeRateInput, QuoteResponse } from '../types.js';
|
|
5
5
|
type NearIntentsTradeContext = {
|
|
6
6
|
tradeCommon: TradeCommon;
|
|
7
7
|
stepCommon: Omit<TradeStepCommon, 'feeData'>;
|
|
@@ -14,7 +14,7 @@ type NearIntentsTradeContext = {
|
|
|
14
14
|
};
|
|
15
15
|
};
|
|
16
16
|
export declare const getNearIntentsTradeContext: ({ input, deps, quote, }: {
|
|
17
|
-
input: NearIntentsTradeQuoteInput | NearIntentsTradeRateInput;
|
|
17
|
+
input: NearIntentsTradeQuoteInput | NearIntentsTradeRateInput | NearIntentsExactOutputTradeQuoteInput | NearIntentsExactOutputTradeRateInput;
|
|
18
18
|
deps: SwapperDeps;
|
|
19
19
|
quote: QuoteResponse['quote'];
|
|
20
20
|
}) => Result<NearIntentsTradeContext, SwapErrorRight>;
|
|
@@ -7,7 +7,7 @@ import { SwapperName } from '../../../types.js';
|
|
|
7
7
|
import { getInputOutputRate, makeTradeStepBuildFailedErr } from '../../../utils/index.js';
|
|
8
8
|
import { buildAffiliateFee } from '../../../utils/affiliateFee.js';
|
|
9
9
|
export const getNearIntentsTradeContext = ({ input, deps, quote, }) => {
|
|
10
|
-
const { sellAsset, buyAsset, affiliateBps,
|
|
10
|
+
const { sellAsset, buyAsset, affiliateBps, slippageTolerancePercentageDecimal } = input;
|
|
11
11
|
if (!quote.depositAddress)
|
|
12
12
|
return Err(makeTradeStepBuildFailedErr('getNearIntentsTradeContext'));
|
|
13
13
|
const rate = getInputOutputRate({
|
|
@@ -16,11 +16,13 @@ export const getNearIntentsTradeContext = ({ input, deps, quote, }) => {
|
|
|
16
16
|
sellAsset,
|
|
17
17
|
buyAsset,
|
|
18
18
|
});
|
|
19
|
+
const isExactOutput = 'buyAmountCryptoBaseUnit' in input;
|
|
19
20
|
return Ok({
|
|
20
21
|
tradeCommon: {
|
|
21
22
|
id: uuid(),
|
|
22
23
|
rate,
|
|
23
24
|
swapperName: SwapperName.NearIntents,
|
|
25
|
+
isExactOutput,
|
|
24
26
|
affiliateBps,
|
|
25
27
|
slippageTolerancePercentageDecimal: slippageTolerancePercentageDecimal ??
|
|
26
28
|
getDefaultSlippageDecimalPercentageForSwapper(SwapperName.NearIntents),
|
|
@@ -51,7 +53,7 @@ export const getNearIntentsTradeContext = ({ input, deps, quote, }) => {
|
|
|
51
53
|
stepDataArgs: {
|
|
52
54
|
deps,
|
|
53
55
|
sellAsset,
|
|
54
|
-
sellAmountCryptoBaseUnit:
|
|
56
|
+
sellAmountCryptoBaseUnit: quote.amountIn,
|
|
55
57
|
depositAddress: quote.depositAddress,
|
|
56
58
|
},
|
|
57
59
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Asset } from '@shapeshiftoss/types';
|
|
2
2
|
import { TxStatus } from '@shapeshiftoss/unchained-client';
|
|
3
3
|
import type { Result } from '@sniptt/monads';
|
|
4
|
-
import type { SwapErrorRight } from '../../../types.js';
|
|
4
|
+
import type { SwapErrorRight, TradeAmount } from '../../../types.js';
|
|
5
5
|
import type { GetExecutionStatusResponse, QuoteResponse } from '../types.js';
|
|
6
6
|
import { QuoteRequest } from '../types.js';
|
|
7
7
|
export declare const getNearIntentsAsset: ({ nearNetwork, contractAddress, }: {
|
|
@@ -20,10 +20,10 @@ export declare const getNearIntentsQuoteDeadline: ({ sellAsset, buyAsset, }: {
|
|
|
20
20
|
sellAsset: Asset;
|
|
21
21
|
buyAsset: Asset;
|
|
22
22
|
}) => string;
|
|
23
|
-
export declare const buildNearIntentsQuoteRequest: ({ originAsset, destinationAsset,
|
|
23
|
+
export declare const buildNearIntentsQuoteRequest: ({ originAsset, destinationAsset, amount, slippageTolerancePercentageDecimal, affiliateBps, refundTo, recipient, refundType, recipientType, deadline, }: {
|
|
24
24
|
originAsset: string;
|
|
25
25
|
destinationAsset: string;
|
|
26
|
-
|
|
26
|
+
amount: TradeAmount;
|
|
27
27
|
slippageTolerancePercentageDecimal: string | undefined;
|
|
28
28
|
affiliateBps: string;
|
|
29
29
|
refundTo: string;
|
|
@@ -127,29 +127,33 @@ export const getNearIntentsQuoteDeadline = ({ sellAsset, buyAsset, }) => {
|
|
|
127
127
|
: DEFAULT_QUOTE_DEADLINE_MS;
|
|
128
128
|
return new Date(Date.now() + deadlineMs).toISOString();
|
|
129
129
|
};
|
|
130
|
-
export const buildNearIntentsQuoteRequest = ({ originAsset, destinationAsset,
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
130
|
+
export const buildNearIntentsQuoteRequest = ({ originAsset, destinationAsset, amount, slippageTolerancePercentageDecimal, affiliateBps, refundTo, recipient, refundType, recipientType, deadline, }) => {
|
|
131
|
+
return {
|
|
132
|
+
dry: false,
|
|
133
|
+
swapType: amount.direction === 'exactOut'
|
|
134
|
+
? QuoteRequest.swapType.EXACT_OUTPUT
|
|
135
|
+
: QuoteRequest.swapType.EXACT_INPUT,
|
|
136
|
+
slippageTolerance: slippageTolerancePercentageDecimal
|
|
137
|
+
? bnOrZero(slippageTolerancePercentageDecimal).times(10000).toNumber()
|
|
138
|
+
: DEFAULT_SLIPPAGE_BPS,
|
|
139
|
+
originAsset,
|
|
140
|
+
destinationAsset,
|
|
141
|
+
amount: amount.cryptoBaseUnit,
|
|
142
|
+
depositType: QuoteRequest.depositType.ORIGIN_CHAIN,
|
|
143
|
+
refundTo,
|
|
144
|
+
refundType,
|
|
145
|
+
recipient,
|
|
146
|
+
recipientType,
|
|
147
|
+
deadline,
|
|
148
|
+
referral: 'shapeshift',
|
|
149
|
+
appFees: [
|
|
150
|
+
{
|
|
151
|
+
recipient: DAO_TREASURY_NEAR,
|
|
152
|
+
fee: Number(affiliateBps),
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
};
|
|
156
|
+
};
|
|
153
157
|
// One retry loop for the SDK's flaky WebSocket transport; maps provider errors to swap errors
|
|
154
158
|
export const fetchNearIntentsQuote = async ({ quoteRequest, sellAsset, }) => {
|
|
155
159
|
const maxRetries = 3;
|
|
@@ -3,6 +3,7 @@ import type { StepDataArgs, SwapErrorRight, TxBuildData } from '../../../types.j
|
|
|
3
3
|
import type { PortalsTx } from './fetchPortalsTradeOrder.js';
|
|
4
4
|
type BaseArgs = {
|
|
5
5
|
tx: PortalsTx;
|
|
6
|
+
sellAmountCryptoBaseUnit: string;
|
|
6
7
|
spenderAddress: string;
|
|
7
8
|
};
|
|
8
9
|
export type GetPortalsStepDataArgs = StepDataArgs<BaseArgs, {
|
|
@@ -4,7 +4,7 @@ import { makeNetworkFeeEstimationFailedErr } from '../../../utils/index.js';
|
|
|
4
4
|
import { estimateGasWithStateOverride, getEvmNetworkFeeCryptoBaseUnit } from '../../../utils/evm/index.js';
|
|
5
5
|
import { fetchPortalsTradeEstimate } from './fetchPortalsTradeOrder.js';
|
|
6
6
|
export async function getPortalsStepData(args) {
|
|
7
|
-
const { tx, sellAsset, spenderAddress, input, deps } = args;
|
|
7
|
+
const { tx, sellAsset, sellAmountCryptoBaseUnit, spenderAddress, input, deps } = args;
|
|
8
8
|
const adapter = deps.assertGetEvmChainAdapter(sellAsset.chainId);
|
|
9
9
|
const supportsEIP1559 = 'supportsEIP1559' in input ? input.supportsEIP1559 : false;
|
|
10
10
|
if (args.type === 'rate') {
|
|
@@ -15,7 +15,7 @@ export async function getPortalsStepData(args) {
|
|
|
15
15
|
try {
|
|
16
16
|
const gasLimit = await estimateGasWithStateOverride({
|
|
17
17
|
sellAsset,
|
|
18
|
-
sellAmountCryptoBaseUnit
|
|
18
|
+
sellAmountCryptoBaseUnit,
|
|
19
19
|
from: tx.from,
|
|
20
20
|
spenderAddress,
|
|
21
21
|
to: tx.to,
|
|
@@ -65,7 +65,7 @@ export async function getPortalsStepData(args) {
|
|
|
65
65
|
supportsEIP1559,
|
|
66
66
|
stateOverride: {
|
|
67
67
|
sellAsset,
|
|
68
|
-
sellAmountCryptoBaseUnit
|
|
68
|
+
sellAmountCryptoBaseUnit,
|
|
69
69
|
spenderAddress,
|
|
70
70
|
},
|
|
71
71
|
});
|
|
@@ -74,6 +74,12 @@ export const getPortalsTradeContext = ({ input, deps, sellChainId, inputToken, o
|
|
|
74
74
|
}),
|
|
75
75
|
},
|
|
76
76
|
protocolFees,
|
|
77
|
-
stepDataArgs: {
|
|
77
|
+
stepDataArgs: {
|
|
78
|
+
deps,
|
|
79
|
+
sellAsset,
|
|
80
|
+
sellAmountCryptoBaseUnit: sellAmountIncludingProtocolFeesCryptoBaseUnit,
|
|
81
|
+
spenderAddress: allowanceContract,
|
|
82
|
+
tx,
|
|
83
|
+
},
|
|
78
84
|
});
|
|
79
85
|
};
|