Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 85 update swap page logic to cosmjs usage #93

Merged
merged 16 commits into from
Jul 25, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ REACT_APP__APP_VERSION=$npm_package_version

# Contract Info
REACT_APP__CHAIN_ID=31337
REACT_APP__CONTRACT_ADDRESS__DUALITY_CORE=0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9
REACT_APP__CONTRACT_ADDRESS__DUALITY_CORE=0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9
REACT_APP__INDEXER_URL=http://localhost:1317/duality/duality/tick
REACT_APP__INDEXER_EVENT_URL=ws://localhost:26657/websocket
dib542 marked this conversation as resolved.
Show resolved Hide resolved
2 changes: 2 additions & 0 deletions .env.template
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
REACT_APP__CHAIN_ID=31337
REACT_APP__CONTRACT_ADDRESS__DUALITY_CORE=0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9
REACT_APP__INDEXER_URL=http://localhost:1317/duality/duality/tick
REACT_APP__INDEXER_EVENT_URL=ws://localhost:26657/websocket
2 changes: 2 additions & 0 deletions .env.test
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
REACT_APP__CHAIN_ID=31337
REACT_APP__CONTRACT_ADDRESS__DUALITY_CORE=0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9
REACT_APP__INDEXER_URL=http://localhost:1317/duality/duality/tick
REACT_APP__INDEXER_EVENT_URL=ws://localhost:26657/websocket
29 changes: 14 additions & 15 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"dependencies": {
"@floating-ui/react-dom": "^0.6.3",
"@reach/dialog": "^0.17.0",
"bignumber.js": "^9.0.2",
"buffer": "^6.0.3",
"ethers": "^5.6.4",
"invariant": "^2.2.4",
Expand Down Expand Up @@ -75,4 +76,4 @@
"last 1 safari version"
]
}
}
}
4 changes: 2 additions & 2 deletions src/components/TokenPicker/mockHooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ const tokens: Array<Token> = [
logo: null,
symbol: 'Dai',
name: 'Dai Stablecoin',
address: '0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512',
address: '0x0002',
},
{
logo: null,
symbol: 'USDC',
name: 'USDCoin',
address: '0x5FbDB2315678afecb367f032d93F642f64180aa3',
address: '0x0003',
},
{ logo: null, symbol: 'USDT', name: 'Tether USD', address: '0x0004' },
{ logo: null, symbol: 'WBTC', name: 'Wrapped BTC', address: '0x0005' },
Expand Down
196 changes: 196 additions & 0 deletions src/lib/web3/indexerProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
import { useContext, createContext, useState, useEffect } from 'react';
import {
EventType,
createSubscriptionManager,
MessageActionEvent,
} from './events';
import { BigNumber } from 'bignumber.js';

const eventsURL = process.env.REACT_APP__INDEXER_EVENT_URL;
if (typeof eventsURL !== 'string' || !eventsURL)
throw new Error(
'Invalid value for env variable REACT_APP__INDEXER_EVENT_URL'
);
const subscriber = createSubscriptionManager(eventsURL);
dib542 marked this conversation as resolved.
Show resolved Hide resolved

export interface PairInfo {
token0: string;
token1: string;
ticks: { [tickID: string]: TickInfo };
}

export interface TickInfo {
price0: BigNumber;
price1: BigNumber;
reserves0: BigNumber;
reserves1: BigNumber;
fee: BigNumber;
}

export interface PairMap {
[pairID: string]: PairInfo;
}

interface IndexerContextType {
pairs: PairMap;
error?: string;
}

const IndexerContext = createContext<IndexerContextType>({
pairs: {},
});

const indexerURL = process.env.REACT_APP__INDEXER_URL;

function getFullData(): Promise<PairMap> {
return new Promise(function (resolve, reject) {
if (!indexerURL) return reject(new Error('Undefined indexer URL'));
fetch(indexerURL)
.then((res) => res.json())
.then(transformData)
.then(resolve)
.catch(reject);
});
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will be limited by the pagination.limit. I noted this a little in https://github.com/duality-labz/duality-web-app/pull/89/files#diff-6229acd4cf5c56748b3fe173cff7f77469038a9815260bdb22f3551091b6b6e0R97-R103 though I didn't address it there, we could do something to be a little more explicit about limit, or do some recursive fetching here. (probably just note the limits for now)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I don't think we gain anything from having this function abstracted out here. It's only used once and its fairly specific. Is it out here for future tests? Its just making me go back and forth between line 42 and line 175 to read it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, just not sure what's the best way of implementing this

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can create another PR for it. I'd like to add a version of the code that I referenced, but that depends on the queryClient that is in #89. What i'd like to do is split off the usage of generated code from #89 into a separate PR that enhances this.


function getPairID(token0: string, token1: string) {
dib542 marked this conversation as resolved.
Show resolved Hide resolved
return `${token0}-${token1}`;
// warning: will throw an error if `tokens` aren't valid hex addresses
// return utils.solidityKeccak256(['address[2]'], [tokens.slice().sort()]);
}

function getTickID(price0: string, price1: string, fee: string) {
return `${price0}-${price1}-${fee}`;
//return utils.solidityKeccak256(['uint256', 'uint256', 'uint256'], [price0, price1, fee]);
}
dib542 marked this conversation as resolved.
Show resolved Hide resolved

function transformData(data: {
tick: Array<{
token0: string;
token1: string;
price0: string;
price1: string;
fee: string;
reserves0: string;
reserves1: string;
}>;
}): Promise<PairMap> {
return new Promise(function (resolve) {
resolve(
dib542 marked this conversation as resolved.
Show resolved Hide resolved
data.tick.reduce<PairMap>(function (
result,
{ token0, token1, price0, price1, fee, reserves0, reserves1 }
) {
const pairID = getPairID(token0, token1);
const tickID = getTickID(price0, price1, fee);
result[pairID] = result[pairID] || {
token0: token0,
token1: token1,
ticks: {},
};
result[pairID].ticks[tickID] = {
price0: new BigNumber(price0),
price1: new BigNumber(price1),
reserves0: new BigNumber(reserves0),
reserves1: new BigNumber(reserves1),
fee: new BigNumber(fee),
};
return result;
},
{})
);
});
}

export function IndexerProvider({ children }: { children: React.ReactNode }) {
const [indexerData, setIndexerData] = useState<{
[pairID: string]: PairInfo;
}>();
dib542 marked this conversation as resolved.
Show resolved Hide resolved
const [error, setError] = useState<string>();
// avoid sending more than once
const [, setRequestedFlag] = useState(false);
const [result, setResult] = useState<IndexerContextType>({
pairs: indexerData ?? {},
error: error,
});

useEffect(() => {
const onTickChange = function (event: MessageActionEvent) {
const {
Token0,
Token1,
NewReserves0,
NewReserves1,
Price0,
Price1,
Fee,
} = event;
if (
!Token0 ||
!Token1 ||
!Price0 ||
!Price1 ||
!NewReserves0 ||
!NewReserves1 ||
!Fee
) {
setError('Invalid event response from server');
return;
}
dib542 marked this conversation as resolved.
Show resolved Hide resolved
const pairID = getPairID(Token0, Token1);
const tickID = getTickID(Price0, Price1, Fee);
setIndexerData((oldData) => {
if (!oldData) oldData = {};
dib542 marked this conversation as resolved.
Show resolved Hide resolved
oldData[pairID] = oldData[pairID] || {
ticks: {},
token0: Token0,
token1: Token1,
};
const tickInfo = oldData[pairID].ticks[tickID] || {
price0: new BigNumber(Price0),
price1: new BigNumber(Price1),
fee: new BigNumber(Fee),
};
tickInfo.reserves0 = new BigNumber(NewReserves0);
tickInfo.reserves1 = new BigNumber(NewReserves1);
oldData[pairID].ticks[tickID] = tickInfo;
dib542 marked this conversation as resolved.
Show resolved Hide resolved
return { ...oldData };
});
};
subscriber.subscribeMessage(onTickChange, EventType.EventTxValue, {
messageAction: 'NewDeposit',
});
subscriber.subscribeMessage(onTickChange, EventType.EventTxValue, {
messageAction: 'NewWithdraw',
});
return () => {
subscriber.unsubscribeMessage(onTickChange);
};
}, []);

useEffect(() => {
setResult({ pairs: indexerData ?? {}, error: error });
dib542 marked this conversation as resolved.
Show resolved Hide resolved
}, [indexerData, error]);

useEffect(() => {
setRequestedFlag((oldValue) => {
if (oldValue) return true;
getFullData()
.then(function (res) {
setIndexerData(res);
})
.catch(function (err: Error) {
setError(err?.message ?? 'Unknown Error');
});
return true;
});
}, []);

return (
<IndexerContext.Provider value={result}>{children}</IndexerContext.Provider>
);
}

export function useIndexerData() {
return useContext(IndexerContext);
}
25 changes: 14 additions & 11 deletions src/pages/App/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Web3Provider } from '../../lib/web3/useWeb3';
import { IndexerProvider } from '../../lib/web3/indexerProvider';

import { BrowserRouter, Routes, Route } from 'react-router-dom';

Expand All @@ -11,17 +12,19 @@ import './App.scss';
function App() {
return (
<Web3Provider>
<BrowserRouter>
<Header />
<main>
<Routes>
<Route index element={<div>Home</div>} />
<Route path="swap" element={<Swap />} />
<Route path="pool" element={<Pool />} />
<Route path="*" element={<div>Not found</div>} />
</Routes>
</main>
</BrowserRouter>
<IndexerProvider>
<BrowserRouter>
<Header />
<main>
<Routes>
<Route index element={<div>Home</div>} />
<Route path="swap" element={<Swap />} />
<Route path="pool" element={<Pool />} />
<Route path="*" element={<div>Not found</div>} />
</Routes>
</main>
</BrowserRouter>
</IndexerProvider>
</Web3Provider>
);
}
Expand Down
12 changes: 12 additions & 0 deletions src/pages/Swap/hooks/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { BigNumber } from 'bignumber.js';

export interface PairRequest {
/** address of altered token */
token0?: string;
Expand All @@ -21,3 +23,13 @@ export interface PairResult {
/** (estimated) gas fee */
gas: string;
}

export interface RouterResult {
amountIn: BigNumber;
tokens: Array<string>;
prices0: Array<Array<BigNumber>>;
prices1: Array<Array<BigNumber>>;
fees: Array<Array<BigNumber>>;
reserves0: Array<Array<BigNumber>>;
reserves1: Array<Array<BigNumber>>;
}
Loading