forked from 0xWizzz/Challenge-scroll-swapAPI
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy path0xWizzz
More file actions
145 lines (125 loc) · 4.62 KB
/
0xWizzz
File metadata and controls
145 lines (125 loc) · 4.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import { config as dotenv } from "dotenv";
import {
createWalletClient,
http,
getContract,
erc20Abi,
parseUnits,
maxUint256,
publicActions,
concat,
numberToHex,
size,
} from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { scroll } from "viem/chains";
import { wethAbi } from "./abi/weth-abi";
dotenv();
const { PRIVATE_KEY, ZERO_EX_API_KEY, ALCHEMY_HTTP_TRANSPORT_URL } = process.env;
if (!PRIVATE_KEY || !ZERO_EX_API_KEY || !ALCHEMY_HTTP_TRANSPORT_URL) {
throw new Error("Missing environment variables.");
}
const headers = new Headers({
"Content-Type": "application/json",
"0x-api-key": ZERO_EX_API_KEY,
"0x-version": "v2",
});
const client = createWalletClient({
account: privateKeyToAccount(`0x${PRIVATE_KEY}` as `0x${string}`),
chain: scroll,
transport: http(ALCHEMY_HTTP_TRANSPORT_URL),
}).extend(publicActions);
const weth = getContract({
address: "0x5300000000000000000000000000000000000004",
abi: wethAbi,
client,
});
const wsteth = getContract({
address: "0xf610A9dfB7C89644979b4A0f27063E9e7d7Cda32",
abi: erc20Abi,
client,
});
// Fetching liquidity sources
const getLiquiditySources = async () => {
try {
const sourcesResponse = await fetch(`https://api.0x.org/swap/v1/sources?chainId=${client.chain.id}`, { headers });
const { sources } = await sourcesResponse.json();
console.log("Liquidity sources:", Object.keys(sources).join(", "));
} catch (error) {
console.error("Error fetching liquidity sources:", error);
}
};
// Display liquidity breakdown
const displayLiquiditySources = (route: any) => {
const totalBps = route.fills.reduce((acc: number, fill: any) => acc + parseInt(fill.proportionBps), 0);
route.fills.forEach((fill: any) => {
console.log(`${fill.source}: ${(parseInt(fill.proportionBps) / totalBps * 100).toFixed(2)}%`);
});
};
// Display token taxes
const displayTokenTaxes = ({ buyToken, sellToken }: any) => {
const formatTax = (taxBps: any) => (parseInt(taxBps) / 100).toFixed(2);
if (buyToken.buyTaxBps > 0 || buyToken.sellTaxBps > 0) {
console.log(`Buy Token Buy Tax: ${formatTax(buyToken.buyTaxBps)}%`);
console.log(`Buy Token Sell Tax: ${formatTax(buyToken.sellTaxBps)}%`);
}
if (sellToken.buyTaxBps > 0 || sellToken.sellTaxBps > 0) {
console.log(`Sell Token Buy Tax: ${formatTax(sellToken.buyTaxBps)}%`);
console.log(`Sell Token Sell Tax: ${formatTax(sellToken.sellTaxBps)}%`);
}
};
// Fetch price and handle monetization
const fetchPriceAndMonetize = async (sellAmount: string) => {
try {
const priceParams = new URLSearchParams({
chainId: client.chain.id.toString(),
sellToken: weth.address,
buyToken: wsteth.address,
sellAmount,
taker: client.account.address,
affiliateFee: "100", // 1% affiliate fee
surplusCollection: "true",
});
const priceResponse = await fetch(`https://api.0x.org/swap/permit2/price?${priceParams.toString()}`, { headers });
const price = await priceResponse.json();
// Approve Permit2 if necessary
if (price.issues?.allowance) {
const { request } = await weth.simulate.approve([price.issues.allowance.spender, maxUint256]);
const hash = await weth.write.approve(request.args);
console.log("Approved Permit2:", await client.waitForTransactionReceipt({ hash }));
}
return price;
} catch (error) {
console.error("Error fetching price:", error);
}
};
// Handle transaction signing
const handleTransaction = async (quote: any, signature: string) => {
try {
const nonce = await client.getTransactionCount({ address: client.account.address });
const signedTransaction = await client.signTransaction({
account: client.account,
chain: client.chain,
gas: BigInt(quote.transaction.gas),
to: quote.transaction.to,
data: quote.transaction.data,
nonce,
});
const hash = await client.sendRawTransaction({ serializedTransaction: signedTransaction });
console.log("Transaction hash:", hash);
} catch (error) {
console.error("Error sending transaction:", error);
}
};
const main = async () => {
await getLiquiditySources();
const decimals = await weth.read.decimals();
const sellAmount = parseUnits("0.1", decimals).toString();
const price = await fetchPriceAndMonetize(sellAmount);
if (price?.route) displayLiquiditySources(price.route);
if (price?.tokenMetadata) displayTokenTaxes(price.tokenMetadata);
const signature = await client.signTypedData(price.permit2.eip712);
price.transaction.data = concat([price.transaction.data, numberToHex(size(signature), { signed: false, size: 32 }), signature]);
await handleTransaction(price, signature);
};
main();