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