2019年12月,Alchemy完成1500万美元A轮融资,资方为Pantera Capital,斯坦福大学,Coinbase,三星等。
2021年4月,Alchemy以5.05亿美元估值完成8000万美元B轮融资,Coatue和Addition领投,DFJ Growth、K5 Global、Chainsmokers(烟鬼组合)、演员Jared Leto和Glazer家族参投。
2021年10月,Alchemy以35亿美元估值完成2.5亿美元C轮融资,由a16z领投的。
2022年2月,Alchemy以102亿美元估值完成2亿美元融资,Lightspeed与Silver Lake领投。
Alchemy是一个背景强大、经费充足、踏实做事、没有发币的团队,这样的项目不刷,难道去刷土狗吗?
并且,Alchemy计划将新资金用于推广Web3采用,这方面的一些举措包括推出Web3 University,就是现在的 Road to Web3 活动,活动为期10周,每周一个NFT。看了下nft数量极少,估计由于任务难度大,很多小伙伴直接放弃,这样的项目若是空投,绝对是大毛。
1.在控制台输入如下代码
git clone https://github.com/0xProject/swap-demo-tutorial.git
2.用vscode打开clone的文件夹。
1.在vscode中进入extensions,在搜索框输入live server ,出来的第一个直接点安装就可以了。
1.将以下代码复制粘贴进swap-demo-tutorial-part-9的index.js替换掉原来的代码。
const qs = require('qs');
const Web3 = require('web3');
const { default: BigNumber } = require('bignumber.js');
let currentTrade = {};
let currentSelectSide;
let tokens;
async function init() {
await listAvailableTokens();
}
async function listAvailableTokens() {
console.log("initializing");
// let response = await fetch('https://tokens.coingecko.com/uniswap/all.json');
// let tokenListJSON = await response.json();
let response='{"name":"CoinGecko","logoURI":"https://www.coingecko.com/assets/thumbnail-007177f3eca19695592f0b8b0eabbdae282b54154e1be912285c9034ea6cbaf2.png","keywords":["defi"],"timestamp":"2022-08-17T04:08:12.925+00:00","tokens":[{"chainId":56,"address":"0x55d398326f99059fF775485246999027B3197955","name":"busd","symbol":"busd","decimals":18,"logoURI":"https://assets.coingecko.com/coins/images/9956/thumb/4943.png?1636636734"},{"chainId":56,"address":"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c","name":"bnb","symbol":"bnb","decimals":18,"logoURI":"https://assets.coingecko.com/coins/images/9956/thumb/4943.png?1636636734"}],"version":{"major":975,"minor":1,"patch":0}}';
let tokenListJSON = JSON.parse(response);
console.log("Listing available tokens: ", tokenListJSON);
tokens = tokenListJSON.tokens;
console.log("tokens: ", tokens);
let parent = document.getElementById("token_list");
for(const i in tokens) {
let div = document.createElement("div");
div.className = "token_row";
let html =
`<img class="token_list_img" src="${tokens[i].logoURI}">
<span class="token_list_text">${tokens[i].symbol}</span>`;
div.innerHTML = html;
div.onclick = () => {
selectToken(tokens[i]);
}
parent.appendChild(div);
}
}
function selectToken(token) {
closeModal();
currentTrade[currentSelectSide] = token;
console.log("currentTrade: ", currentTrade);
renderInterface();
}
function renderInterface() {
if(currentTrade.from) {
document.getElementById("from_token_img").src = currentTrade.from.logoURI;
document.getElementById("from_token_text").innerHTML = currentTrade.from.symbol;
}
if(currentTrade.to) {
document.getElementById("to_token_img").src = currentTrade.to.logoURI;
document.getElementById("to_token_text").innerHTML = currentTrade.to.symbol;
}
}
async function connect() {
if (typeof window.ethereum !== "undefined") {
try {
console.log("Connecting");
await ethereum.request({ method: "eth_requestAccounts" });
} catch (error) {
console.log(error);
}
document.getElementById("login_button").innerHTML = "Connected";
document.getElementById("swap_button").disabled = false;
} else {
document.getElementById("login_button").innerHTML =
"Please install Metamask";
}
}
async function getPrice() {
console.log("Getting Price");
if(!currentTrade.from || !currentTrade.to || !document.getElementById("from_amount").value) return;
let amount = Number(document.getElementById("from_amount").value * 10 ** currentTrade.from.decimals);
const params = {
sellToken: currentTrade.from.address,
buyToken: currentTrade.to.address,
sellAmount: amount,
}
// Fetch the swap price
const response = await fetch(`https://bsc.api.0x.org/swap/v1/price?${qs.stringify(params)}`);
swapPriceJSON = await response.json();
console.log("Price: ", swapPriceJSON);
document.getElementById("to_amount").value = swapPriceJSON.buyAmount / (10 ** currentTrade.to.decimals);
document.getElementById("gas_estimate").innerHTML = swapPriceJSON.estimatedGas;
}
async function getQuote(account) {
console.log("Getting Quote");
if(!currentTrade.from || !currentTrade.to || !document.getElementById("from_amount").value) return;
let amount = Number(document.getElementById("from_amount").value * 10 ** currentTrade.from.decimals);
const params = {
sellToken: currentTrade.from.symbol,
buyToken: currentTrade.to.symbol,
sellAmount: amount,
takerAddress: account,
slippagePercentage: 0.05
};
// Fetch the swap price
const response = await fetch(`https://bsc.api.0x.org/swap/v1/quote?${qs.stringify(params)}`);
swapQuoteJSON = await response.json();
console.log("Quote: ", swapQuoteJSON);
// document.getElementById("to_amount").value = swapQuoteJSON.price;
document.getElementById("gas_estimate").innerHTML = swapQuoteJSON.estimatedGas;
return swapQuoteJSON;
}
async function trySwap() {
let accounts = await ethereum.request({ method: "eth_accounts" });
let takerAddress = accounts[0];
console.log("takerAddress:", takerAddress);
const swapQuoteJSON = await getQuote(takerAddress);
// Set Token Allowance
// Interact with ERC20TokenContract
const web3 = new Web3(Web3.givenProvider);
const fromTokenAddress = currentTrade.from.address;
const erc20abi = [{ "inputs": [ { "internalType": "string", "name": "name", "type": "string" }, { "internalType": "string", "name": "symbol", "type": "string" }, { "internalType": "uint256", "name": "max_supply", "type": "uint256" } ], "stateMutability": "nonpayable", "type": "constructor" }, { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "owner", "type": "address" }, { "indexed": true, "internalType": "address", "name": "spender", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } ], "name": "Approval", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "from", "type": "address" }, { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } ], "name": "Transfer", "type": "event" }, { "inputs": [ { "internalType": "address", "name": "owner", "type": "address" }, { "internalType": "address", "name": "spender", "type": "address" } ], "name": "allowance", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "spender", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "approve", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "account", "type": "address" } ], "name": "balanceOf", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "burn", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "account", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "burnFrom", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "decimals", "outputs": [ { "internalType": "uint8", "name": "", "type": "uint8" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "spender", "type": "address" }, { "internalType": "uint256", "name": "subtractedValue", "type": "uint256" } ], "name": "decreaseAllowance", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "spender", "type": "address" }, { "internalType": "uint256", "name": "addedValue", "type": "uint256" } ], "name": "increaseAllowance", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "name", "outputs": [ { "internalType": "string", "name": "", "type": "string" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "symbol", "outputs": [ { "internalType": "string", "name": "", "type": "string" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "totalSupply", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "recipient", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "transfer", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "sender", "type": "address" }, { "internalType": "address", "name": "recipient", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "transferFrom", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" }]
console.log("trying swap");
const ERC20TokenContract = new web3.eth.Contract(erc20abi, fromTokenAddress);
console.log("setup ERC20TokenContract: ", ERC20TokenContract);
const maxApproval = new BigNumber(2).pow(256).minus(1);
console.log("approval amount: ", maxApproval);
const tx = await ERC20TokenContract.methods
.approve(swapQuoteJSON.allowanceTarget, maxApproval)
.send({ from: takerAddress })
.then((tx) => {
console.log("tx: ", tx)
});
const receipt = await web3.eth.sendTransaction(swapQuoteJSON);
console.log("receipt: ", receipt);
}
init();
function openModal(side) {
currentSelectSide = side;
document.getElementById("token_modal").style.display = "block";
}
function closeModal() {
document.getElementById("token_modal").style.display = "none";
}
document.getElementById("login_button").onclick = connect;
document.getElementById("from_token_select").onclick = () => {
openModal("from");
};
document.getElementById("to_token_select").onclick = () => {
openModal("to");
};
document.getElementById("modal_close").onclick = closeModal;
document.getElementById("from_amount").onblur = getPrice;
document.getElementById("swap_button").onclick = trySwap;
1.在控制台输入以下代码,安装相关modules。
npm i qs
npm i bignumber
npm i web3
npm install -g browserify
browserify index.js --standalone bundle -o bundle.js
1.回到vscode,选中index.html,右键点击open with live server。
2.会出现这样的界面
当然,也可以在index.html的第31行和40行加入“选择币种”字样,保存后在运行就会变成这样,不过这个无所谓,根本不影响。
3.点击右上角链接小狐狸钱包。
4.点击选择币种那里,官方原版代码会出现好多币,也不知道哪个币是哪个链上的,直接ctrl+f找找你有的币就行。然后我这里用jay改过的的index.js的代码,就会只有两个币选择。
5.输入一定数额完成兑换即可,然后将交易的hash复制下来,留着等会提交。
1.登录github,点击New。
2.这三个地方填一下,然后直接拉到最下面,点击Create repository。
3.点击code,复制仓库地址备用。
4..接下来就到本地操作了,首先确保你已经成功安装Git这个软件,在电脑上找到你要上传到Github上面的那个项目文件夹,进入项目文件夹,单击鼠标右键,选择Git Bash Here,如下图所示。
5.接下来输入如下代码(关键步骤),把github上面的仓库克隆到本地
6.这个步骤以后你的本地项目文件夹下面就会多出个文件夹,该文件夹名即为你github上面的项目名,如图我多出了个road-to-web3-09文件夹,我们把本地项目文件夹下的所有文件(除了新多出的那个文件夹不用),其余都复制到那个新多出的文件夹下。
7.接着继续输入命令 cd road-to-web3-09,进入road-to-web3-09文件夹(road-to-web3-09是我建的仓库,这里应该改成你自己的仓库名字)
8.接下来依次输入以下代码即可完成其他剩余操作:
git add . (注:别忘记后面的 . ,此操作是把Test文件夹下面的文件都添加进来)
git commit -m "提交信息" (注:“提交信息”里面换成你需要,也可以不管,这里可能会出现如下第一张图提示,按照提示输入git config --global user.email "you@example.com"
git config --global user.name "Your Name" 就可以了 )
git push -u origin main (注:此操作目的是把本地仓库push到github上面,此步骤需要你输入帐号和密码)
9.第一次使用Git,会弹框要求登录,把这个码复制下来。
10.点第九步码下面那个链接,进去登录自己的git账号,然后把把复制粘贴在这里,授权就可以了。
11.复制这个链接即可。
注意,提交github代码地址和交易的合约地址。