Skip to content

Commit 4cf163b

Browse files
committed
Change default tokenlist to custom one
1 parent ee98955 commit 4cf163b

File tree

8 files changed

+250
-4
lines changed

8 files changed

+250
-4
lines changed

bun.lockb

12.5 KB
Binary file not shown.

packages/evmcrispr/src/modules/std/helpers/token.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,17 @@ import {
1414
} from "../../../utils";
1515
import type { Module } from "../../../Module";
1616
import type { Std } from "../Std";
17+
import type { BindingsManager } from "../../../BindingsManager";
1718

1819
const ENV_TOKENLIST = "$token.tokenlist";
19-
const DEFAULT_TOKEN_LIST = "https://tokens.uniswap.org/";
2020

21-
const getTokenList = ({ bindingsManager }: Module): string => {
21+
const getTokenList = async (
22+
bindingsManager: BindingsManager,
23+
chainId: number,
24+
): Promise<string> => {
2225
const tokenList = String(
2326
bindingsManager.getBindingValue(ENV_TOKENLIST, BindingsSpace.USER) ??
24-
DEFAULT_TOKEN_LIST,
27+
`https://tokens.functions.on-fleek.app/v0/${chainId}`,
2528
);
2629

2730
// Always check user data inputs:
@@ -41,7 +44,7 @@ export const _token = async (
4144
return tokenSymbolOrAddress;
4245
}
4346
const chainId = await module.getChainId();
44-
const tokenList = getTokenList(module);
47+
const tokenList = await getTokenList(module.bindingsManager, chainId);
4548
const {
4649
tokens,
4750
}: { tokens: { symbol: string; chainId: number; address: string }[] } =

packages/token-list/README.md

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Token List
2+
3+
## Installation and Usage
4+
5+
### Installation
6+
7+
First, install the required dependencies using:
8+
9+
```sh
10+
bun i
11+
```
12+
13+
### Building the Project
14+
15+
To build the project, use the following command:
16+
17+
```sh
18+
bun run build
19+
```
20+
21+
This will create a `./dist/main.js` bundle that includes all tree-shaken dependencies.
22+
23+
### Deployment
24+
25+
To deploy the project, follow these steps:
26+
27+
1. Create a function:
28+
29+
```sh
30+
bun create-func $NAME
31+
```
32+
33+
2. Deploy the function:
34+
35+
```sh
36+
bun deploy-func $NAME
37+
```
38+
39+
Replace `$NAME` with the desired name of your function.

packages/token-list/biome.json

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
3+
"vcs": {
4+
"enabled": true,
5+
"clientKind": "git",
6+
"useIgnoreFile": true
7+
},
8+
"organizeImports": {
9+
"enabled": false
10+
},
11+
"linter": {
12+
"enabled": true,
13+
"rules": {
14+
"recommended": true
15+
}
16+
},
17+
"formatter": {
18+
"enabled": true,
19+
"indentWidth": 2,
20+
"indentStyle": "space"
21+
}
22+
}

packages/token-list/package.json

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "evmcrispr-token-list",
3+
"private": true,
4+
"version": "0.0.0",
5+
"type": "module",
6+
"main": "./src/main.ts",
7+
"scripts": {
8+
"build": "tsc src/main.ts && rollup -c",
9+
"create-func": "fleek functions create --name",
10+
"deploy-func": "fleek functions deploy --noBundle --path dist/main.js --name",
11+
"lint": "biome check --write && biome format --write && biome lint --write"
12+
},
13+
"devDependencies": {
14+
"@biomejs/biome": "^1.8.3",
15+
"@rollup/plugin-node-resolve": "^13.0.6",
16+
"@rollup/plugin-typescript": "^11.1.6",
17+
"rollup": "^2.60.0",
18+
"typescript": "^5.2.2"
19+
},
20+
"license": "MIT"
21+
}

packages/token-list/rollup.config.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { nodeResolve } from "@rollup/plugin-node-resolve";
2+
import typescript from "@rollup/plugin-typescript";
3+
4+
export default {
5+
input: "src/main.ts",
6+
output: {
7+
dir: "dist",
8+
format: "es",
9+
inlineDynamicImports: true,
10+
banner: 'import { Buffer } from "node:buffer";',
11+
},
12+
plugins: [
13+
nodeResolve(), // Needed to bundle the assets from node_modules
14+
typescript(),
15+
],
16+
};

packages/token-list/src/coingecko.ts

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
type Network = {
2+
id: string;
3+
chain_identifier: number | null;
4+
name: string;
5+
shortname: string;
6+
native_coin_id: string;
7+
};
8+
9+
export async function getNetworkName(
10+
chainId: number,
11+
): Promise<{ name: string; id: string }> {
12+
const networks: Network[] = await fetch(
13+
"https://api.coingecko.com/api/v3/asset_platforms",
14+
).then((res) => res.json());
15+
const network = networks.find(
16+
(network) => network.chain_identifier === chainId,
17+
);
18+
if (!network) {
19+
throw {
20+
status: 404,
21+
body: "Network not found",
22+
};
23+
}
24+
return { name: network.name, id: network.id };
25+
}

packages/token-list/src/main.ts

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import { getNetworkName } from "./coingecko";
2+
3+
type RequestObject = {
4+
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD";
5+
headers?: {
6+
[key: string]: string;
7+
} | null;
8+
path: string;
9+
query?: {
10+
[key: string]: string | string[];
11+
} | null;
12+
body?: string | null;
13+
};
14+
15+
type ResponseObject =
16+
| {
17+
status: number;
18+
headers?: {
19+
[key: string]: string;
20+
} | null;
21+
body?: string;
22+
}
23+
| string
24+
| ArrayBuffer;
25+
26+
export async function main(params: RequestObject): Promise<ResponseObject> {
27+
try {
28+
const { chainId } = processParams(params);
29+
const { name: networkName, id: networkId } = await getNetworkName(chainId);
30+
const coingeckoTokenList = `https://tokens.coingecko.com/${networkId}/all.json`;
31+
const superfluidTokenList =
32+
"https://raw.githubusercontent.com/superfluid-finance/tokenlist/main/superfluid.extended.tokenlist.json";
33+
const tokenLists = await Promise.all([
34+
fetch(coingeckoTokenList).then((res) => res.json()),
35+
fetch(superfluidTokenList).then((res) => res.json()),
36+
]);
37+
const lastTimestamp = Math.max(
38+
...tokenLists.map((tokenList) => new Date(tokenList.timestamp).getTime()),
39+
);
40+
const tokenList = {
41+
name: `EVMcrispr Token List (${networkName})`,
42+
logoURI: "https://evmcrispr.com/favicon.ico",
43+
timestamp: new Date(lastTimestamp).toISOString(),
44+
tokens: tokenLists[0].tokens
45+
.concat(
46+
tokenLists[1].tokens.filter((token) => token.chainId === chainId),
47+
)
48+
.reduce((acc, token) => {
49+
if (acc.find((t) => t.address === token.address)) {
50+
return acc;
51+
}
52+
acc.push(token);
53+
return acc;
54+
}, []),
55+
version: {
56+
patch: 1,
57+
},
58+
};
59+
return {
60+
status: 200,
61+
headers: {
62+
"Content-Type": "application/json",
63+
"Access-Control-Allow-Origin": "*",
64+
},
65+
body: JSON.stringify(tokenList),
66+
};
67+
} catch (error) {
68+
if (isErrorWithStatusAndBody(error)) {
69+
return error;
70+
}
71+
return {
72+
status: 500,
73+
body: "Internal Server Error",
74+
};
75+
}
76+
}
77+
78+
// main({ method: "GET", path: "/v0/1" }).then((res) => {
79+
// console.log(res);
80+
// });
81+
82+
function isErrorWithStatusAndBody(
83+
error: unknown,
84+
): error is { status: number; body: string } {
85+
const err = error as { [key: string]: unknown };
86+
return (
87+
err &&
88+
typeof err === "object" &&
89+
typeof err.status === "number" &&
90+
typeof err.body === "string"
91+
);
92+
}
93+
94+
function processParams(params: RequestObject): { chainId: number } {
95+
const { method, path } = params;
96+
97+
if (method !== "GET") {
98+
throw {
99+
status: 405,
100+
body: "Method Not Allowed",
101+
};
102+
}
103+
104+
if (!path.startsWith("/v0/")) {
105+
throw {
106+
status: 400,
107+
body: "Invalid URL",
108+
};
109+
}
110+
const [, , chainId] = path.split("/");
111+
112+
if (!Number(chainId)) {
113+
throw {
114+
status: 400,
115+
body: "Invalid chainId",
116+
};
117+
}
118+
119+
return { chainId: Number(chainId) };
120+
}

0 commit comments

Comments
 (0)