Graph
This commit is contained in:
parent
c98c1833b7
commit
8f0542a520
|
@ -11,7 +11,6 @@ Program Flow:
|
|||
* [X] Download token contract state to determine contract types and basic info.
|
||||
* [X] Download swap contract state to determine contract types.
|
||||
* [X] Continually download state of swap contracts, to ensure liquidity and pricing information is up to date.
|
||||
* [ ] Construct swap graph.
|
||||
|
||||
- Logging in:
|
||||
* [X] User presses relevant login button.
|
||||
|
@ -19,7 +18,7 @@ Program Flow:
|
|||
|
||||
- Trading (Write!):
|
||||
* [X] User selects tokens and amount to move between.
|
||||
* [ ] Compute shortest route; dijkstra's. (Can use one, or several weight algorithms: Liquidity, price, etc.)
|
||||
* [X] Compute shortest route; dijkstra's. (Can use one, or several weight algorithms: Liquidity, price, etc.)
|
||||
* [ ] Present route, fees, gas usage, etc.
|
||||
* [ ] User presses TRADE!
|
||||
* [ ] Sends transactions: _Approve to router_ and _route_ with the given route.
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
"hash.js": "^1.1.7",
|
||||
"partisia-blockchain-applications-sdk": "^0.1.2",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"bip32-path": "^0.4.2"
|
||||
"bip32-path": "^0.4.2",
|
||||
"graphology": "^0.25.4",
|
||||
"graphology-shortest-path": "2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-transform-runtime": "^7.19.6",
|
||||
|
|
|
@ -19,6 +19,8 @@ import { NETWORK } from "../constant";
|
|||
import { AvlClient } from "../client/AvlClient";
|
||||
import {TokenV1Contract } from "../token/contract/TokenV1Contract";
|
||||
import {TokenV2Contract } from "../token/contract/TokenV2Contract";
|
||||
import UndirectedGraph from 'graphology';
|
||||
import dijkstra from 'graphology-shortest-path/dijkstra';
|
||||
|
||||
// UI constants
|
||||
const TOKEN_LIST = <Element>document.querySelector("#token-list");
|
||||
|
@ -31,15 +33,22 @@ type ContractType = "token_v1" | "token_v2" | "swap_lock_v1"
|
|||
|
||||
interface ContractState {
|
||||
address: BlockchainAddress,
|
||||
latest_state: TokenStateV1 | TokenStateV2 | null;
|
||||
swaps: BlockchainAddress[] | null,
|
||||
type: ContractType | null,
|
||||
latest_state: TokenStateV1 | TokenStateV2 | null;
|
||||
}
|
||||
|
||||
interface TokenContractState extends ContractState {
|
||||
}
|
||||
|
||||
interface SwapContractState extends ContractState {
|
||||
swapTokens: BlockchainAddress[],
|
||||
}
|
||||
|
||||
interface Route {
|
||||
from: BlockchainAddress | null,
|
||||
to: BlockchainAddress | null,
|
||||
swaps: BlockchainAddress[],
|
||||
tokenContracts: string[],
|
||||
swapContracts: string[],
|
||||
user: BlockchainAddress | null,
|
||||
}
|
||||
|
||||
|
@ -47,11 +56,11 @@ const ROUTERS: BlockchainAddress[] = [BlockchainAddress.fromString("02f8eb18e09d
|
|||
|
||||
type BlockchainAddressKey = string;
|
||||
|
||||
const TOKENS: Record<BlockchainAddressKey, ContractState> = {};
|
||||
const TOKENS: Record<BlockchainAddressKey, TokenContractState> = {};
|
||||
|
||||
const SWAPS: Record<BlockchainAddressKey, ContractState> = {};
|
||||
const SWAPS: Record<BlockchainAddressKey, SwapContractState> = {};
|
||||
|
||||
const CURRENT_ROUTE: Route = { from: null, to: null, swaps: [], user: null };
|
||||
const CURRENT_ROUTE: Route = { from: null, to: null, tokenContracts: [], swapContracts: [], user: null };
|
||||
|
||||
const SHARDED_CLIENT: ShardedClient = new ShardedClient(NETWORK.node_base_url, NETWORK.network_shards);
|
||||
const AVL_CLIENT:AvlClient = new AvlClient(NETWORK .node_base_url, NETWORK.network_shards);;
|
||||
|
@ -78,7 +87,6 @@ function address_to_url(address: BlockchainAddress): string {
|
|||
}
|
||||
|
||||
function setInnerText(query: string, text: string) {
|
||||
console.log(query, text);
|
||||
for (const a of document.querySelectorAll(query)) {
|
||||
(<HTMLElement>a).innerText = text;
|
||||
}
|
||||
|
@ -97,18 +105,43 @@ function ui_show_route() {
|
|||
|
||||
setInnerText("[data-input-token]", symbolFrom);
|
||||
setInnerText("[data-output-token]", symbolTo);
|
||||
|
||||
setInnerText("[data-route-list]", "");
|
||||
(<Element>document.querySelector("[data-route-list]")).innerHTML = CURRENT_ROUTE.swapContracts.map(s => `<div>${s}</div>`).join("");
|
||||
}
|
||||
|
||||
function get_swap_graph(): UndirectedGraph {
|
||||
const graph = new UndirectedGraph();
|
||||
for (const addrStr in TOKENS) {
|
||||
graph.addNode(addrStr);
|
||||
}
|
||||
for (const addrStr in SWAPS) {
|
||||
const swap = SWAPS[addrStr];
|
||||
graph.addEdgeWithKey(addrStr, swap.swapTokens[0].asString(), swap.swapTokens[1].asString(), { liquidity: 1000 });
|
||||
}
|
||||
return graph;
|
||||
}
|
||||
|
||||
function node_path_to_edge_path(graph: UndirectedGraph, nodePath: string[]): string[] {
|
||||
const edgeRoute = [];
|
||||
for (let idx = 0; idx < nodePath.length - 1; idx++) {
|
||||
edgeRoute.push(graph.edges(nodePath[idx], nodePath[idx+1])[0]);
|
||||
}
|
||||
|
||||
return edgeRoute;
|
||||
}
|
||||
|
||||
function reroute() {
|
||||
console.log("Rerouting", CURRENT_ROUTE);
|
||||
|
||||
// Do not route if from or to are not assigned yet.
|
||||
if (CURRENT_ROUTE.from == null || CURRENT_ROUTE.to == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform routing.
|
||||
// TODO
|
||||
const graph = get_swap_graph();
|
||||
|
||||
CURRENT_ROUTE.tokenContracts = dijkstra.bidirectional(graph, CURRENT_ROUTE.from.asString(), CURRENT_ROUTE.to.asString(), (_, attr) => attr.liquidity);
|
||||
CURRENT_ROUTE.swapContracts = node_path_to_edge_path(graph, CURRENT_ROUTE.tokenContracts);
|
||||
|
||||
ui_show_route();
|
||||
}
|
||||
|
@ -232,7 +265,6 @@ async function get_token_state(tokenAddress: BlockchainAddress): Promise<[TokenS
|
|||
}
|
||||
|
||||
async function get_token_balance(info: ContractState, account: BlockchainAddress): Promise<BN> {
|
||||
console.log(info);
|
||||
if (info.type == "token_v2") {
|
||||
return await new TokenV2Contract(SHARDED_CLIENT, undefined).tokenBalance(info.address, account);
|
||||
} else {
|
||||
|
@ -263,14 +295,11 @@ function setup() {
|
|||
|
||||
// Setup routes
|
||||
for (let router of ROUTERS) {
|
||||
console.log(router);
|
||||
get_contract_state(router, deserializeRouterState).then((state) => {
|
||||
console.log(state);
|
||||
|
||||
for (const swapInfo of state.swapContracts) {
|
||||
TOKENS[swapInfo.tokenAAddress.asString()] = { latest_state: null, swaps: null, type: null, address: swapInfo.tokenAAddress };
|
||||
TOKENS[swapInfo.tokenBAddress.asString()] = { latest_state: null, swaps: null, type: null, address: swapInfo.tokenBAddress };
|
||||
SWAPS[swapInfo.swapAddress.asString()] = { latest_state: null, swaps: [swapInfo.tokenAAddress, swapInfo.tokenBAddress], type: null, address: swapInfo.swapAddress };
|
||||
TOKENS[swapInfo.tokenAAddress.asString()] = { latest_state: null, type: null, address: swapInfo.tokenAAddress };
|
||||
TOKENS[swapInfo.tokenBAddress.asString()] = { latest_state: null, type: null, address: swapInfo.tokenBAddress };
|
||||
SWAPS[swapInfo.swapAddress.asString()] = { latest_state: null, swapTokens: [swapInfo.tokenAAddress, swapInfo.tokenBAddress], type: null, address: swapInfo.swapAddress };
|
||||
ui_add_swap(swapInfo.swapAddress);
|
||||
}
|
||||
|
||||
|
|
|
@ -106,7 +106,7 @@
|
|||
type="submit"
|
||||
value="Exchange!" />
|
||||
|
||||
<div class="route-list">
|
||||
<div class="route-list" data-route-list="">
|
||||
<div>1000 A to 3000 B (0.3% fee)</div>
|
||||
<div>3000 B to 9000 C (0.3% fee)</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue
Block a user