Skip to content

Commit 912689a

Browse files
authored
added oracle_amm (#5)
1 parent b764c22 commit 912689a

33 files changed

+2120
-0
lines changed

price_feeds/evm/oracle_swap/README.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Pyth Oracle AMM
2+
3+
This directory contains an example oracle AMM application using Pyth price feeds.
4+
The oracle AMM manages a pool of two tokens and allows a user to trade with the pool at the current Pyth price.
5+
6+
This application has two components. The first component is a smart contract (in the `contract` directory) that manages the pool and implements the trading functionality.
7+
The second is a frontend application (in the `app` directory) that communicates with the smart contract.
8+
9+
Please see the [Pyth documentation](https://docs.pyth.network/documentation/pythnet-price-feeds) for more information about Pyth and how to integrate it into your application.
10+
11+
**Warning** this AMM is intended only as a demonstration of Pyth price feeds and is **not for production use**.
12+
13+
## AMM Contract
14+
15+
All of the commands in this section expect to be run from the `contract` directory.
16+
17+
### Building
18+
19+
You need to have [Foundry](https://getfoundry.sh/) and `node` installed to run this example.
20+
Once you have installed these tools, run the following commands from the [`contract`](./contract) directory to install openzeppelin and forge dependencies:
21+
22+
```
23+
forge install foundry-rs/[email protected] --no-git --no-commit
24+
forge install OpenZeppelin/[email protected] --no-git --no-commit
25+
```
26+
27+
After installing the above dependencies, you need to install pyth-sdk-solidity.
28+
29+
```
30+
npm init -y
31+
npm install @pythnetwork/pyth-sdk-solidity
32+
```
33+
34+
### Testing
35+
36+
Simply run `forge test` in the [`contract`](./contract) directory. This command will run the
37+
tests located in the [`contract/test`](./contract/test) directory.
38+
39+
### Deploying
40+
41+
To deploy the contract, you first need to configure the target network and the tokens in the AMM pool.
42+
Edit the configuration parameters in the [deploy script](./contract/scripts/deploy.sh) and then run it using `./scripts/deploy.sh`.
43+
The code comments in that file should help you populate the parameters correctly.
44+
45+
If you don't have ERC-20 tokens to test with, you can use the [token deploy script](./contract/scripts/deploy_token.sh) to create some for testing.
46+
Edit the configuration parameters in there before running to set the network and token name.
47+
This will deploy a new mock token and print out a contract address.
48+
Once you have this address, you can mint the token anytime using the following command:
49+
50+
```
51+
cast send --rpc-url <RPC_URL> -l <ERC20_CONTRACT_ADDRESS> "mint(address,uint256)" <YOUR_WALLET_ADDRESS> <QUANTITY_IN_WEI>
52+
```
53+
54+
When the contract is deployed, the token pools are initially empty.
55+
You will need to send some funds to the pool for testing purposes.
56+
You can use the following command to transfer ERC-20 tokens from your wallet to the contract:
57+
58+
```
59+
cast send --rpc-url <RPC_URL> -l <ERC20_CONTRACT_ADDRESS> "transfer(address,uint256)" <DESTINATION_ADDRESS> <QUANTITY_IN_WEI>
60+
```
61+
62+
### Create ABI
63+
64+
If you change the contract, you will need to create a new ABI.
65+
The frontend uses this ABI to create transactions.
66+
You can overwrite the existing ABI by running the following command:
67+
68+
```
69+
forge inspect OracleSwap abi > ../app/src/abi/OracleSwapAbi.json
70+
```
71+
72+
## Frontend Application
73+
74+
By default, the frontend is configured to use the already deployed version of the oracle AMM
75+
at address [`0x15F9ccA28688F5E6Cbc8B00A8f33e8cE73eD7B02`](https://mumbai.polygonscan.com/address/0x15F9ccA28688F5E6Cbc8B00A8f33e8cE73eD7B02) on Polygon Mumbai.
76+
This means you can start playing with the application without going through the steps above (Remember to switch your wallet to Mumbai and to claim funds from a faucet to pay for the gas).
77+
78+
### Build
79+
80+
From the `app/` directory, run the following commands to install dependencies and build the frontend:
81+
82+
```
83+
npm i
84+
npm run build
85+
```
86+
87+
### Run
88+
89+
After building, you can start the frontend by navigating to the `app/` directory and running:
90+
91+
`npm run start`
92+
93+
Then navigate your browser to `localhost:3000`.
94+
95+
### Other configurations:
96+
97+
optimism goerli addresses
98+
brl 0x8e2a09b54fF35Cc4fe3e7dba68bF4173cC559C69
99+
usd 0x98cDc14fe999435F3d4C2E65eC8863e0d70493Df
100+
swap contract 0xf3161b2B32761B46C084a7e1d8993C19703C09e7
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"name": "@pythnetwork/eth-oracle-swap-example-frontend",
3+
"version": "0.1.0",
4+
"private": true,
5+
"dependencies": {
6+
"@pythnetwork/pyth-evm-js": "*",
7+
"@pythnetwork/pyth-sdk-solidity": "*",
8+
"@testing-library/jest-dom": "^5.16.5",
9+
"@testing-library/react": "^13.4.0",
10+
"@testing-library/user-event": "^13.5.0",
11+
"@types/jest": "^27.5.2",
12+
"@types/node": "^16.11.64",
13+
"@types/react": "^18.0.21",
14+
"@types/react-dom": "^18.0.6",
15+
"buffer": "^6.0.3",
16+
"ethers": "^5.7.2",
17+
"metamask-react": "^2.4.0",
18+
"prettier": "^2.7.1",
19+
"react": "^18.2.0",
20+
"react-dom": "^18.2.0",
21+
"react-scripts": "5.0.1",
22+
"typescript": "^4.8.4",
23+
"web-vitals": "^2.1.4",
24+
"web3": "^1.8.0"
25+
},
26+
"scripts": {
27+
"start": "react-scripts start",
28+
"build": "react-scripts build",
29+
"eject": "react-scripts eject",
30+
"format": "prettier --write src/"
31+
},
32+
"eslintConfig": {
33+
"extends": [
34+
"react-app",
35+
"react-app/jest"
36+
]
37+
},
38+
"browserslist": {
39+
"production": [
40+
">0.2%",
41+
"not dead",
42+
"not op_mini all"
43+
],
44+
"development": [
45+
"last 1 chrome version",
46+
"last 1 firefox version",
47+
"last 1 safari version"
48+
]
49+
}
50+
}
Binary file not shown.
Binary file not shown.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1" />
7+
<meta name="theme-color" content="#000000" />
8+
<meta
9+
name="description"
10+
content="Example oracle AMM application using Pyth price feeds."
11+
/>
12+
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
13+
<!--
14+
manifest.json provides metadata used when your web app is installed on a
15+
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
16+
-->
17+
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
18+
<!--
19+
Notice the use of %PUBLIC_URL% in the tags above.
20+
It will be replaced with the URL of the `public` folder during the build.
21+
Only files inside the `public` folder can be referenced from the HTML.
22+
23+
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
24+
work correctly both with client-side routing and a non-root public URL.
25+
Learn how to configure a non-root public URL by running `npm run build`.
26+
-->
27+
<title>Pyth Example Oracle AMM</title>
28+
<script>
29+
const faviconTag = document.querySelector("link[rel~='icon']");
30+
const isDark = window.matchMedia("(prefers-color-scheme: dark)");
31+
const changeFavicon = () => {
32+
if (isDark.matches) faviconTag.href = "/favicon-light.ico";
33+
else faviconTag.href = "/favicon.ico";
34+
};
35+
changeFavicon();
36+
setInterval(changeFavicon, 1000);
37+
</script>
38+
</head>
39+
<body>
40+
<noscript>You need to enable JavaScript to run this app.</noscript>
41+
<div id="root"></div>
42+
<!--
43+
This HTML file is a template.
44+
If you open it directly in the browser, you will see an empty page.
45+
46+
You can add webfonts, meta tags, or analytics to this file.
47+
The build step will place the bundled scripts into the <body> tag.
48+
49+
To begin the development, run `npm start` or `yarn start`.
50+
To create a production bundle, use `npm run build` or `yarn build`.
51+
-->
52+
</body>
53+
</html>
5.22 KB
Loading
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"short_name": "React App",
3+
"name": "Create React App Sample",
4+
"icons": [
5+
{
6+
"src": "favicon.ico",
7+
"sizes": "64x64 32x32 24x24 16x16",
8+
"type": "image/x-icon"
9+
},
10+
{
11+
"src": "logo192.png",
12+
"type": "image/png",
13+
"sizes": "192x192"
14+
}
15+
],
16+
"start_url": ".",
17+
"display": "standalone",
18+
"theme_color": "#000000",
19+
"background_color": "#ffffff"
20+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# https://www.robotstxt.org/robotstxt.html
2+
User-agent: *
3+
Disallow:
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
.App {
2+
text-align: left;
3+
display: flex;
4+
}
5+
6+
.control-panel {
7+
flex: 1;
8+
background-color: #282c34;
9+
min-height: 100vh;
10+
max-width: fit-content;
11+
display: flex;
12+
flex-direction: column;
13+
justify-content: flex-start;
14+
color: white;
15+
padding: 5px;
16+
}
17+
18+
.main {
19+
flex: 1;
20+
padding: 0 20px;
21+
}
22+
23+
.tab-header {
24+
display: flex;
25+
}
26+
27+
.tab-item {
28+
flex: 1;
29+
text-align: center;
30+
padding: 10px;
31+
cursor: pointer;
32+
background-color: #ddd;
33+
border: 1px solid black;
34+
}
35+
36+
.tab-item.active {
37+
background-color: #fff;
38+
border-bottom: 0px;
39+
}
40+
41+
.tab-content {
42+
padding: 10px;
43+
border: 1px solid black;
44+
border-top: 0px;
45+
}
46+
47+
.icon-container {
48+
display: inline-block;
49+
position: relative;
50+
text-decoration: underline;
51+
}
52+
53+
.tooltip {
54+
position: absolute;
55+
top: 5px; /* adjust as needed */
56+
left: 30px; /* adjust as needed */
57+
background-color: #333;
58+
color: #fff;
59+
padding: 5px 10px;
60+
border-radius: 3px;
61+
font-size: 12px;
62+
visibility: hidden;
63+
opacity: 0;
64+
transition: all 0.3s ease-in-out;
65+
width: 200px;
66+
}
67+
68+
.icon-container:hover .tooltip {
69+
visibility: visible;
70+
opacity: 1;
71+
}
72+
73+
.exchange-rate {
74+
color: green;
75+
}
76+
77+
.last-updated {
78+
color: #777;
79+
}
80+
81+
h1,
82+
h2,
83+
h3,
84+
h4,
85+
h5,
86+
p,
87+
input {
88+
padding: 0;
89+
margin: 0;
90+
}
91+
92+
h3 {
93+
margin: 30px 0px 3px;
94+
}
95+
96+
p {
97+
margin: 5px 0px 6px 0px;
98+
}
99+
100+
input[type="text"] {
101+
padding: 3px;
102+
margin: 10px 5px;
103+
text-align: right;
104+
}
105+
106+
.swap-steps {
107+
margin: 10px 0px;
108+
}
109+
110+
button {
111+
margin: 0px 5px 0px 5px;
112+
}

0 commit comments

Comments
 (0)