1
0
This commit is contained in:
Jon Michael Aanes 2024-06-10 23:56:58 +02:00
parent c98c1833b7
commit 8f0542a520
Signed by: Jmaa
SSH Key Fingerprint: SHA256:Ab0GfHGCblESJx7JRE4fj4bFy/KRpeLhi41y4pF3sNA
4 changed files with 51 additions and 21 deletions

View File

@ -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.

View File

@ -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",

View File

@ -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);
}

View File

@ -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>