Skip to content

Commit

Permalink
feat: air swap route
Browse files Browse the repository at this point in the history
  • Loading branch information
Rickk137 committed Nov 8, 2023
1 parent 27645c8 commit cb6c400
Show file tree
Hide file tree
Showing 8 changed files with 565 additions and 14 deletions.
5 changes: 5 additions & 0 deletions apps/frontend/craco.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ module.exports = {
/Configure maximumFileSizeToCacheInBytes to change this limit/,
];
config.resolve.fallback = {
http: require.resolve('stream-http'),
https: require.resolve('https-browserify'),
net: false,
tls: false,
zlib: require.resolve('browserify-zlib'),
stream: require.resolve('stream-browserify'),
buffer: require.resolve('buffer'),
crypto: require.resolve('crypto-browserify'),
Expand Down
3 changes: 2 additions & 1 deletion packages/sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,17 @@
"dist"
],
"dependencies": {
"@airswap/libraries": "4.1.9",
"@sovryn-zero/lib-ethers": "0.2.5",
"@sovryn/contracts": "*",
"@sovryn/ethers-provider": "*",
"rxjs": "7.5.6"
},
"peerDependencies": {
"ethers": "*",
"@ethersproject/abstract-provider": "*",
"@ethersproject/providers": "*",
"@sovryn-zero/lib-base": "*",
"ethers": "*",
"@sovryn/contracts": "*"
}
}
24 changes: 24 additions & 0 deletions packages/sdk/src/_tests/swaps/routes/air-swap-route.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { airSwapRoute } from '../../../swaps/smart-router/routes/air-swap-route';
import { SwapRoute } from '../../../swaps/smart-router/types';
import { makeChainFixture } from '../../_fixtures/chain';
import { TEST_TIMEOUT } from '../../config';

describe('AIR Swap Route', () => {
jest.setTimeout(TEST_TIMEOUT);

let route: SwapRoute;

beforeAll(async () => {
const fixture = await makeChainFixture();
route = airSwapRoute(fixture.provider);
});

it('has correct name', () => {
expect(route.name).toEqual('AIR');
});

it('has pairs', async () => {
const pairs = await route.pairs();
expect(pairs.size).toBeGreaterThan(0);
});
});
4 changes: 2 additions & 2 deletions packages/sdk/src/_tests/swaps/smart-router.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe('SmartRouter', () => {

describe('getAvailableRoutes', () => {
it('return all available routes', async () => {
expect(router.getAvailableRoutes()).toHaveLength(4);
expect(router.getAvailableRoutes()).toHaveLength(5);
});
});

Expand Down Expand Up @@ -115,7 +115,7 @@ describe('SmartRouter', () => {
});

it('returns all available entries', async () => {
await expect(router.getEntries()).resolves.toHaveLength(8);
await expect(router.getEntries()).resolves.toHaveLength(9);
});

it('returns all available destinations for entry token', async () => {
Expand Down
2 changes: 2 additions & 0 deletions packages/sdk/src/swaps/smart-router/config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { airSwapRoute } from './routes/air-swap-route';
import { ammSwapRoute } from './routes/amm-swap-route';
import { mocIntegrationSwapRoute } from './routes/moc-integration-swap-route';
import { myntBassetRoute } from './routes/mynt-basset-route';
Expand All @@ -7,4 +8,5 @@ export const DEFAULT_SWAP_ROUTES: SwapRouteFunction[] = [
ammSwapRoute,
myntBassetRoute,
mocIntegrationSwapRoute,
airSwapRoute,
];
2 changes: 2 additions & 0 deletions packages/sdk/src/swaps/smart-router/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { airSwapRoute } from './routes/air-swap-route';
import { ammSwapRoute } from './routes/amm-swap-route';
import { mocIntegrationSwapRoute } from './routes/moc-integration-swap-route';
import { myntBassetRoute } from './routes/mynt-basset-route';
Expand All @@ -13,4 +14,5 @@ export const smartRoutes = {
myntBassetRoute,
zeroRedemptionSwapRoute,
mocIntegrationSwapRoute,
airSwapRoute,
};
148 changes: 148 additions & 0 deletions packages/sdk/src/swaps/smart-router/routes/air-swap-route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import { Registry, SwapERC20 } from '@airswap/libraries';

import { BigNumber, constants, providers } from 'ethers';

import { SupportedTokens, getTokenContract } from '@sovryn/contracts';
import { ChainId, numberToChainId } from '@sovryn/ethers-provider';

import { SovrynErrorCode, makeError } from '../../../errors/errors';
import {
canSwapPair,
makeApproveRequest,
hasEnoughAllowance,
} from '../../../internal/utils';
import { SwapPairs, SwapRouteFunction } from '../types';

export const airSwapRoute: SwapRouteFunction = (
provider: providers.Provider,
) => {
let pairCache: SwapPairs;
let chainId: ChainId;

const getChainId = async () => {
if (!chainId) {
chainId = numberToChainId((await provider.getNetwork()).chainId);
}
return chainId;
};

const getOrder = async (entry, destination, amount, from) => {
const baseToken = await validatedTokenAddress(entry);
const quoteToken = await validatedTokenAddress(destination);
const chainId = await getChainId();

const servers = await Registry.getServers(
provider,
Number(chainId),
baseToken,
quoteToken,
);

const order = servers[0].getSignerSideOrderERC20(
amount.toString(),
baseToken,
quoteToken,
from,
);

return order;
};

const validatedTokenAddress = async (token: string) => {
token = token.toLowerCase();

return token;
};

return {
name: 'AIR',
pairs: async () => {
if (!pairCache) {
const chainId = await getChainId();

const swapTokens = [SupportedTokens.rusdt, SupportedTokens.dllr];

const contracts = await Promise.all(
swapTokens.map(token => getTokenContract(token, chainId)),
);

const addresses = contracts.map(contract =>
contract.address.toLowerCase(),
);

const pairs = new Map<string, string[]>();

for (const address of addresses) {
const pair = addresses.filter(a => a !== address);
pairs.set(address, pair);
}

pairCache = pairs;
}

return pairCache;
},
quote: async (entry, destination, amount) => {
const order = await getOrder(
entry,
destination,
amount,
constants.AddressZero,
);
return BigNumber.from((await order).signerAmount);
},
approve: async (entry, destination, amount, from, overrides) => {
const chainId = await getChainId();
const contractAddress = SwapERC20.getAddress(Number(chainId));

if (
!contractAddress ||
(await hasEnoughAllowance(
provider,
entry,
contractAddress,
from,
amount ?? constants.MaxUint256,
))
) {
return undefined;
}

return {
...makeApproveRequest(
entry,
contractAddress,
amount ?? constants.MaxUint256,
),
...overrides,
};
},
permit: async () => Promise.resolve(undefined),
async swap(entry, destination, amount, from, options, overrides) {
const pairs = await this.pairs();
if (!canSwapPair(entry, destination, pairs)) {
throw makeError(
`Cannot swap ${entry} to ${destination}`,
SovrynErrorCode.SWAP_PAIR_NOT_AVAILABLE,
);
}

const order = await getOrder(
entry,
destination,
amount,
constants.AddressZero,
);
const swapContract = SwapERC20.getContract(provider, Number(chainId));

const tx = await swapContract.swapLight(order);

return {
to: tx.to,
data: tx.data,
value: amount.toString(),
...overrides,
};
},
};
};
Loading

0 comments on commit cb6c400

Please sign in to comment.