5-29
1 npm依赖dependencies与devDependencies
仔细品味下面两段话:
"dependencies"
:您的应用程序在生产中所需的包。"devDependencies"
:只需要本地开发和测试的包。
[1] 在 package.json 文件中指定依赖项和 devDependencies.https://docs.npmjs.com/specifying-dependencies-and-devdependencies-in-a-package-json-file
2 babel
Babel 是源码到源码的编译器(转换编译器(transpiler))
作用
- 转换语法
- Polyfill 目标环境中缺少的功能(通过如 core-js 的第三方
polyfill
) - 源代码转换(codemods)
预设
一组 Babel 插件和/或 options
配置的可共享模块,有几个常见 官方预设
:
- @babel/preset-env for compiling ES2015+ syntax
- @babel/preset-typescript for TypeScript
- @babel/preset-react for React
当然,其他库会有自己的预设,例如:Next.js | Nuxt.js | Parcel | Jest | Gatsby
处理步骤
三个主要处理步骤分别是:解析(parse),转换(transform),生成(generate)
sourcemap:记录了源码到目标代码的转换关系,通过它我们可以找到目标代码中每一个节点对应的源 码位置
[2] babel中文文档.https://www.babeljs.cn/docs/presets
2 babel、webpack插件
3 webpack
4 cra配置站点地图
通过 [1] 进行操作,失败
示例项目
https://github.com/ginlink/cool-uilib/tree/main/apps/cra_17_sitemap
解决方案
两步:1.配置路由 2.配置执行脚本
第一步:配置路由
./src/Routes.tsx
import { Redirect, Route, Switch } from 'react-router-dom'
import React from 'react'
export default function Routes() {
return (
<Switch>
<Route exact path="/home" render={() => <div />} />
<Route exact path="/about" render={() => <div />} />
<Redirect from="/" to="/home" />
</Switch>
)
}
第二步:配置 执行脚本
./sitemap-builder.ts
interface RouterRoute {
props: { path: string }
}
interface SitemapRoute {
path: string
}
import fs from 'fs'
import path from 'path'
import dotenv from 'dotenv'
// routes
import Router from './src/Routes'
const envFilename = './.env.production'
const buildPath = './public/sitemap.xml'
const dotenvFile = path.resolve(__dirname, envFilename)
if (!fs.existsSync(dotenvFile)) {
console.error(`No ${envFilename} file found. Halting...`) // eslint-disable-line no-console
process.exit(1)
}
dotenv.config({ path: dotenvFile })
const { PUBLIC_URL } = process.env // I am pulling my baseUrl from env - you can generate it however you want
const routes = (Router()?.props.children || [])
.reduce((acc: SitemapRoute[], route: RouterRoute) => {
if (Array.isArray(route)) {
return [...acc, ...route.map((subRoute) => ({ path: subRoute.props?.path }))]
}
return [...acc, { path: route.props?.path }]
}, [])
.filter((route: SitemapRoute) => route.path)
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${routes.reduce(
(acc: string, route: SitemapRoute) => `${acc}
<url>
<loc>${PUBLIC_URL}/#${route.path}</loc>
<lastmod>${new Date().toISOString().slice(0, 10)}</lastmod>
<priority>0.8</priority/>
</url>`,
''
)}
</urlset>
`
fs.writeFileSync(buildPath, xml)
console.info(`> ✔️ Sitemap successfully generated at ${buildPath}`)
./tsconfig.node.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
},
}
./.env.production
PUBLIC_URL=https://gincool.com
./package.json
{
"scripts": {
"sitemap": "NODE_PATH=./ npx ts-node --project ./tsconfig.node.json ./sitemap-builder.ts"
}
}
最后运行
在 ./public/
中生成sitemap.xml文件
yarn sitemap
[1] Create sitemap for your REACT app.https://blog.josedromero.com/create-sitemap-for-your-react-app/
5 kex_exchange_identification: Connection closed by remote host Connection closed by 127.0.0.1 port 7890
原因
代理问题 | ssh/config配置问题
场景
已挂代理,浏览器可以访问github,但命令行无法连接github服务器
报错
kex_exchange_identification: Connection closed by remote host Connection closed by 127.0.0.1 port 7890
解决方案
编辑 ~/.ssh/config
并添加
Host github.com
Hostname ssh.github.com
Port 443
[1]ssh_exchange_identification: Connection closed by remote host under Git bash closed].https://stackoverflow.com/questions/10127818/ssh-exchange-identification-connection-closed-by-remote-host-under-git-bash/60994276#60994276?newreg=fb268194e55d4ccba80299a54417534f
6 给monorepo添加包
yarn workspace <workspace_name> add <package_name>
例如:
yarn workspace @ginlink/cra_17_sitemap add react-gradient-text
[1] How to avoid install of packages in monorepo using Yarn.https://stackoverflow.com/questions/60874627/how-to-avoid-install-of-packages-in-monorepo-using-yarn
7 WETH与ETH区别
由来
抹平代币种类问题,将其他种类转化为ERC20代币
这里种类问题可能是精度等问题
例如:一个币GIN的精度是6位,WGIN是18位
过程
WETH9合约
功能: 有两个方法质押、赎回,将其他币质押,输出ERC20代币,同理,赎回则返回原有的代币
[1] WETH9源码.https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2#code
8 部署uniswapV2
步骤汇总
- 准备合约地址
- 替换部分包内容 sdk-core和v2-sdk
- 更改路由地址、链支持、流动性追踪代币(查流动性)、路由中间人(查路由)
- 杂项:更改区块浏览器地址、交易列表
步骤一:准备合约地址
名称与源码地址:
- factory合约.https://etherscan.io/address/0x5c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f#code
- router2合约.https://etherscan.io/address/0x7a250d5630b4cf539739df2c5dacb4c659f2488d#code
- weth9合约.https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2#code
- multicalV3合约.https://etherscan.io/address/0x5ba1e12693dc8f9c48aad8770482f4739beed696#code
注意一:部署factory合约时,给Factory添加如下属性,用于查询INIT_CODE_PAIR_HASH
bytes32 public constant INIT_CODE_PAIR_HASH = keccak256(abi.encodePacked(type(UniswapV2Pair).creationCode));
注意二:部署router合约时,替换init code
,如果不替换,无法交易
kcc链(322)地址:
factory(11774332):0xF72Ad9009e81181E342153b20e8afe8aD21DA3e7
wkcs:0xB296bAb2ED122a85977423b602DdF3527582A3DA
router2:0xB493638903016751fe5A5Ca61080A19D9af1793a
INIT_CODE_HASH:0x84a902c06264b6d04c9b7841473fa6e0634300f5331c41061f26ab4ce126de78
huobi链(256)地址:
factory:0x8b6A47e50CEF56c4e68b88C3aBaaEa86773710E7
wht:0x7af326b6351c8a9b8fb8cd205cbe11d4ac5fa836
router2:0x582070e7e499b401c093Ea6B63a6FC9066A1Fb26
INIT_CODE_HASH:0x15c4dfb595cfab7511d8e4f6d0a7fb1b28a953422e9d8079effd944a872973fe
bsc链(97)地址:
factory:0xEd5eCBD035efCC275D31f4D799e98EcCA3320080
wbnb:0xABbc0dB80d50e4175CEC6A0efd43994a00c19b5F
router2:0x423FEDe43B47A70caE3A50238bCFED8fAE529Fe7
INIT_CODE_HASH:0x15c4dfb595cfab7511d8e4f6d0a7fb1b28a953422e9d8079effd944a872973fe
替换部分包内容 sdk-core/v2-sdk
更改sdk-core的 weth9
,支持其他链
更改v2-sdk的 factory地址
和 INIT_CODE_HASH
修改完毕,发包
包别名解析
发包成功后,利用npm的别名解析,将@uniswap/sdk-core和@uniswap/v2-sdk分别指向自己发布的包,例如
顶级的 package.json
{
"resolutions": {
"babel-loader": "8.1.0",
"@types/react": "^17.0.1",
"@web3-react/abstract-connector": "^6.0.7",
// 指定解析地址
"@uniswap/sdk-core": "npm:@ginlink/uni-sdk-core@^0.1.1",
"@uniswap/v2-sdk": "npm:@ginlink/uni-v2-sdk@^0.1.1"
}
}
注意: npm源的地址,如果是包刚发布到npm,那么淘宝源等是不会立马同步过来的,所以会找不到,此时,
利用 npx nrm use npm
切换到官方源
更改路由地址、链支持、流动性追踪代币、路由中间人
更改路由地址和multicall地址
/src/constants/addresses.ts
=>> V2_ROUTER_ADDRESS
=>> MULTICALL_ADDRESS
链支持
/src/constants/chains.ts
=>> SupportedChainId
=>> ALL_SUPPORTED_CHAIN_IDS
钱包支持
/src/constants/wallet.ts
=>> SUPPORTED_WALLETS
流动性追踪代币和路由中间人
一个用于查流动性、一个用于查路由
如果没有流动性追踪,那么则需要手动导入流动性
如果没有路由中间人,那么无法进行夸池子交易
/src/constants/routing.ts
=>> BASES_TO_TRACK_LIQUIDITY_FOR
=>> BASES_TO_CHECK_TRADES_AGAINST
杂项:更改区块浏览器地址、交易列表
修改完上面内容,就可以进行添加|移除流动性、交易了,但有一些杂项需要处理
更改区块浏览器地址
apps/coolswap/src/utils/getExplorerLink.ts
=>> ETHERSCAN_PREFIXES
交易列表
apps/coolswap/src/constants/lists.ts
=>> DEFAULT_LIST_OF_LISTS_TO_DISPLAY
=>> DEFAULT_ACTIVE_LIST_URLS
其他更改
改写uniswap路由查找功能为v2
由于修改时间点为2022-06-06,基于最新uniswap前端代码改写,uniswap目前偏向于v3,所以很多v2的内容逐渐被转移和废弃。其中路由查找方面,uniswap采用了客户端+服务端共同查找的方案,而且客户端只支持v3的路由查找,所以需要改写
示例项目: coolswap
https://github.com/ginlink/swap
9 TSDX
[1] https://tsdx.io/
10 发包前的钩子命令
例如:发包前执行 tsdx build
{
"scripts": {
"prepublishOnly": "tsdx build"
}
}
11 jsdelivr免费cdn加速
https://cdn.jsdelivr.net/gh/ginlink/[email protected]/
[1] 免费CDN:jsDelivr+Github 使用方法.https://zhuanlan.zhihu.com/p/76951130
12 正则断言
[1] 正则表达式中断言的使用以及简单例子.https://blog.csdn.net/keheinash/article/details/103063843
13 coingecko接口地址
coingecko可以查询各个链的币种信息,例如价格等
https://www.coingecko.com/en/api/documentation
示例
https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd
# ids可以是地址,也可以是别名
14 在线比较两个json
在线比较两个json,并将两者差异标记出来
https://www.sojson.com/jsondiff.html
15 eslint自动修复未使用导入模块
注意,无法自动修复未使用声明,因为涉及的东西会很多
解决方案
使用 eslint-plugin-unused-imports
插件,跟着 [2] 文档走吧
[1] How can I remove unused imports/declarations from the entire project of React Typescript?.https://stackoverflow.com/questions/64365300/how-can-i-remove-unused-imports-declarations-from-the-entire-project-of-react-ty
[2] eslint-plugin-unused-imports.https://github.com/sweepline/eslint-plugin-unused-imports
16 typescript 中的 interface 和 type 到底有什么区别?
[1] typescript 中的 interface 和 type 到底有什么区别?.https://github.com/SunshowerC/blog/issues/7#%E9%83%BD%E5%85%81%E8%AE%B8%E6%8B%93%E5%B1%95extends
17 UniswapV2价格影响率
对单个池子的影响率
场景
BTC-USDC池子数目:329999BTC, 10.9999USDC
假设,当前输入1个BTC,预计收到为27424.3,那么价格影响率为:
(27424.3 - (329999/10.9999)) / (329999/10.9999) = -0.08586220694608164,即 8.59% 左右
即 (预计收到 - 最优情况下收到) / 最优情况下收到
18 常用组件的罗列与封装
描述
利用storebook管理
依赖
- styled-system
- styled-components
- storebook
需要完成列表如下:
组件名称 | 组件描述 | 实现方式描述 | 常用度 | 是否完成 |
---|---|---|---|---|
Box | 包裹容器 | - | ⭐️⭐️⭐️⭐️⭐️ | |
Row | flex横向布局 | 利用flex实现 | ⭐️⭐️⭐️⭐️⭐️ | |
Column | flex纵向布局 | 利用grid实现 | ⭐️⭐️⭐️ | |
Button | 按钮 | - | ⭐️⭐️⭐️⭐️⭐️ | |
Input | 输入框 | - | ⭐️⭐️⭐️⭐️⭐️ | |
Radio | 单选框 | ⭐️ | ||
Checkbox | 复选框 | ⭐️ | ||
Table | 表格 | ⭐️⭐️ | ||
Typography | 排版 | ⭐️⭐️⭐️⭐️⭐️ | ||
Img | 图片 | ⭐️⭐️⭐️ | ||
Link | 链接 | ⭐️⭐️ | ||
Card | 卡片 | ⭐️⭐️⭐️ | ||
DropMenu | 下拉菜单 | ⭐️⭐️ | ||
TreeMenu | 树状菜单 | ⭐️ | ||
TabMenu | tab菜单 | ⭐️ | ||
BottomMenu | 下方移动端菜单 | ⭐️ | ||
Tooltip | 弹出小提示 | ⭐️ | ||
Message | 消息提示 | ⭐️ | ||
Alert | 弹出层提示 | ⭐️ | ||
Stepper | 步骤条 | ⭐️ | ||
Slider | 滑块 | ⭐️ |
19 批量删除git分支
本地
删除单条本地分支
git branch -d dev111
删除单个本地tag
git tag -d v0.1.0
批量删除本地分支
git branch | grep 'dev/*' | xargs git branch \-d
批量删除本地tag
git tag -l | awk '/v1.0.0-RC[0-6]/' | xargs git tag -d
远端
删除单条远端分支
git push origin :dev111
# 语法 git push origin <本地>:<远端>
# 如果本地、远端都给,就表示推送分支到远端
# 如果不给本地,就表示删除云端分支
删除单个远端tag
git push origin :v0.1.0
批量删除远端tag
git show-ref --tag | awk '/v1.0.0-RC[0-6]/ {print ":" $2}' | xargs git push origin
[1] Git批量删除本地分支.https://segmentfault.com/a/1190000022215551
[2] git 添加tag,删除tag,批量删除tag.https://blog.csdn.net/m0_37628958/article/details/109493671
import { setLocale, getLocale } from 'di18n-react'
import { Select } from 'antd'
enum LOCALES {
'zh-CN' = 'zh-CN',
'zh-TW' = 'zh-TW',
}
type LanguageLabels = {
[key in LOCALES | string]: string
}
const Lang = () => {
const selectedLang = getLocale()
const languageLabels: LanguageLabels = {
'zh-CN': '简体中文',
'zh-TW': '繁体中文',
}
const handleLangChange = (key: string) => {
setLocale(key, { cookieLocaleKey: 'lang' })
window.location.reload()
}
return (
<Select defaultValue={selectedLang ?? 'zh-CN'} style={{ width: 100 }} bordered={false} onChange={handleLangChange}>
{Object.keys(languageLabels).map((item, index) => (
<Select.Option value={item} key={index}>
{languageLabels[item]}
</Select.Option>
))}
</Select>
)
}
export default Lang