Skip to content

Commit c53812b

Browse files
committed
added demo
1 parent 44516d0 commit c53812b

File tree

5 files changed

+978
-0
lines changed

5 files changed

+978
-0
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Carbon SDK - Concentrated AMM Integration Demo
2+
3+
This project demonstrates how Carbon strategies can be adapted for use with services that require a concentrated AMM format by leveraging the Carbon-to-Concentrated-AMM adapter.
4+
5+
## Prerequisites
6+
7+
- Node.js (v14 or higher)
8+
- Yarn or npm
9+
- Alchemy API key (or another Ethereum provider)
10+
11+
## Installation
12+
13+
Clone the repository and install dependencies:
14+
15+
```bash
16+
git clone <repository-url>
17+
cd carbon-integration-demo
18+
yarn install
19+
# or
20+
npm install
21+
```
22+
23+
## Configuration
24+
25+
Before running the demo, you need to configure your Ethereum provider:
26+
27+
1. Open `demo.ts`
28+
2. Replace `<YOUR_API_KEY>` in the `PROVIDER_URL` constant with your Alchemy API key:
29+
30+
```typescript
31+
const PROVIDER_URL = 'https://eth-mainnet.g.alchemy.com/v2/<YOUR_API_KEY>';
32+
```
33+
34+
## Running the Demo
35+
36+
You can run the demo in the following ways:
37+
38+
### Using ts-node (development)
39+
40+
This will run the TypeScript file directly without explicit compilation:
41+
42+
```bash
43+
yarn dev
44+
# or
45+
npm run dev
46+
```
47+
48+
### Build and Run
49+
50+
First compile the TypeScript to JavaScript, then run the compiled code:
51+
52+
```bash
53+
# Build
54+
yarn build
55+
# or
56+
npm run build
57+
58+
# Run
59+
yarn start
60+
# or
61+
npm start
62+
```
63+
64+
## What the Demo Does
65+
66+
1. Connects to the Ethereum mainnet (via your configured provider)
67+
2. Queries for Carbon StrategyUpdated events, handling only the ones with `reason` TRADE.
68+
3. Extracts relevant information from each Carbon strategy and transforms it into an object that represents a position in a concentrated AMM.
69+
4. Demonstrates how a service could consume this converted data
70+
71+
## Notes
72+
73+
- This is a demo application. For production use, you should implement proper error handling and configuration management.
74+
- The integration demonstrates how to transform Carbon strategies into a concentrated AMM format, making them compatible with services that expect concentrated liquidity position data.
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
/**
2+
* Carbon SDK - UniswapV3 Integration Demo
3+
*
4+
* This demo shows how Carbon strategies can be used with Services that expect UniswapV3 format
5+
* by leveraging the Carbon-to-UniswapV3 adapter.
6+
*/
7+
8+
import { ethers } from 'ethers';
9+
import { Contracts } from '@bancor/carbon-sdk/contracts-api';
10+
import { castToUniV3, UniV3CastStrategy } from '@bancor/carbon-sdk/adapters';
11+
import { EncodedStrategy } from '@bancor/carbon-sdk';
12+
import { decodeStrategy } from '@bancor/carbon-sdk/strategy-management';
13+
14+
// Mock typical types to demonstrate integration
15+
enum AMMAlgorithm {
16+
UniswapV3 = 'UniswapV3',
17+
// Other AMMs would be listed here
18+
}
19+
20+
// RPC provider URL including API key
21+
const PROVIDER_URL =
22+
'https://eth-mainnet.g.alchemy.com/v2/oBk4KxWELF9-8Grh_bEds_Y6T2OVMoYL';
23+
24+
const REASON_TRADE = 1; // Event reason for trade
25+
26+
/**
27+
* Main function to demonstrate integration with Carbon
28+
*/
29+
async function demonstrateCarbonIntegration() {
30+
console.log('Starting Carbon integration demo...');
31+
32+
// Initialize provider with proper error handling
33+
const provider = new ethers.providers.StaticJsonRpcProvider(PROVIDER_URL);
34+
35+
// Initialize Carbon contracts
36+
const contracts = new Contracts(provider, {
37+
carbonControllerAddress: '0xC537e898CD774e2dCBa3B14Ea6f34C93d5eA45e1',
38+
voucherAddress: '0x3660F04B79751e31128f6378eAC70807e38f554E',
39+
carbonBatcherAddress: '0x0199f3A6C4B192B9f9C3eBE31FBC535CdD4B7D4e',
40+
multiCallAddress: '0xcA11bde05977b3631167028862bE2a173976CA11',
41+
});
42+
43+
// const reader = new Reader(contracts);
44+
45+
// Start syncing data (in a real implementation)
46+
console.log('Initializing Carbon data sync...');
47+
48+
// Get current block for demo purposes
49+
const currentBlock = await provider.getBlockNumber();
50+
const fromBlock = currentBlock - 1000; // Look back 1000 blocks for demo
51+
52+
console.log(
53+
`Querying for StrategyUpdated events from block ${fromBlock} to ${currentBlock}`
54+
);
55+
56+
// Create filter for StrategyUpdated events with reason REASON_TRADE
57+
const filter = contracts.carbonController.filters.StrategyUpdated(
58+
null, // id
59+
null, // token0
60+
null, // token1
61+
null, // order0
62+
null, // order1
63+
null // reason - using null instead of REASON_TRADE to match expected parameter type
64+
);
65+
66+
// Query for events
67+
const logs = await contracts.carbonController.queryFilter(
68+
filter,
69+
fromBlock,
70+
currentBlock
71+
);
72+
73+
console.log(`Found ${logs.length} StrategyUpdated events`);
74+
75+
const tradeLogs = logs.filter((log) => log.args?.reason === REASON_TRADE);
76+
77+
console.log(`Found ${tradeLogs.length} trade events`);
78+
79+
// Process each event
80+
for (const log of tradeLogs) {
81+
const eventArgs = log.args;
82+
if (!eventArgs) continue;
83+
84+
const strategyId = eventArgs.id;
85+
const token0 = eventArgs.token0;
86+
const token1 = eventArgs.token1;
87+
const order0 = eventArgs.order0;
88+
const order1 = eventArgs.order1;
89+
90+
// Construct the encoded strategy from event data
91+
const carbonStrategy: EncodedStrategy = {
92+
id: strategyId,
93+
token0,
94+
token1,
95+
order0: {
96+
y: order0.y,
97+
z: order0.z,
98+
A: order0.A,
99+
B: order0.B,
100+
},
101+
order1: {
102+
y: order1.y,
103+
z: order1.z,
104+
A: order1.A,
105+
B: order1.B,
106+
},
107+
};
108+
109+
console.log(`Processing Carbon strategy ID: ${strategyId.toString()}`);
110+
console.log("here's a breakdown of the strategy:", {
111+
token0: token0,
112+
token1: token1,
113+
order0: {
114+
y: order0.y.toString(),
115+
z: order0.z.toString(),
116+
A: order0.A.toString(),
117+
B: order0.B.toString(),
118+
},
119+
order1: {
120+
y: order1.y.toString(),
121+
z: order1.z.toString(),
122+
A: order1.A.toString(),
123+
B: order1.B.toString(),
124+
},
125+
});
126+
127+
// Just for educational purposes, let's decode the strategy
128+
const decodedStrategy = decodeStrategy(carbonStrategy);
129+
console.log("here's a breakdown of the decoded strategy:", {
130+
token0: decodedStrategy.token0,
131+
token1: decodedStrategy.token1,
132+
order0: decodedStrategy.order0,
133+
order1: decodedStrategy.order1,
134+
});
135+
136+
// Convert Carbon strategy to UniswapV3 format using the adapter
137+
const uniV3Strategy = castToUniV3(carbonStrategy);
138+
console.log(`here's a breakdown of the uniV3 strategy:`, uniV3Strategy);
139+
140+
// Demonstrate how an integrator could consume this data
141+
demonstrateIntegratorConsumption(uniV3Strategy);
142+
}
143+
}
144+
145+
/**
146+
* Demonstrates how an integrator could consume the converted Carbon strategy
147+
*/
148+
function demonstrateIntegratorConsumption(uniV3Strategy: UniV3CastStrategy) {
149+
console.log('Integrator consumption of converted Carbon strategy:');
150+
151+
// Extract data that integrator would use
152+
const { pool, sellOrder, buyOrder } = uniV3Strategy;
153+
154+
// Mock integrator data structures based on the provided code
155+
const integratorData = {
156+
// Pool information
157+
pool: {
158+
token0: pool.xAxisToken,
159+
token1: pool.yAxisToken,
160+
tickSpacing: pool.tickSpacing,
161+
},
162+
163+
// Position information (combining both orders for demonstration)
164+
positions: [
165+
{
166+
// Sell order position
167+
tickLower: sellOrder.tickLower,
168+
tickUpper: sellOrder.tickUpper,
169+
liquidity: sellOrder.liquidity,
170+
sqrtPriceX96: sellOrder.sqrtPriceX96,
171+
},
172+
{
173+
// Buy order position
174+
tickLower: buyOrder.tickLower,
175+
tickUpper: buyOrder.tickUpper,
176+
liquidity: buyOrder.liquidity,
177+
sqrtPriceX96: buyOrder.sqrtPriceX96,
178+
},
179+
],
180+
181+
// Global state information (using sell order for demonstration)
182+
globalState: {
183+
sqrtPriceX96: sellOrder.sqrtPriceX96,
184+
},
185+
};
186+
187+
// Demonstrate mapping to integrator's expected format
188+
console.log('Mapped to integrator format:');
189+
console.log(`Pool: ${pool.yAxisToken} / ${pool.xAxisToken}`);
190+
console.log(`Tick Spacing: ${pool.tickSpacing}`);
191+
192+
// Show how integrator would access position data using their constants
193+
console.log('\nAccessing data using integrators constants:');
194+
195+
// For UniswapV3 algorithm
196+
const algorithm = AMMAlgorithm.UniswapV3;
197+
198+
// Token addresses
199+
console.log(`Token0 (${Token0[algorithm]}): ${integratorData.pool.token0}`);
200+
console.log(`Token1 (${Token1[algorithm]}): ${integratorData.pool.token1}`);
201+
202+
// Position data
203+
console.log('\nPosition data:');
204+
integratorData.positions.forEach((position, index) => {
205+
console.log(`Position ${index + 1}:`);
206+
console.log(
207+
`- ${DecodePositionsTickLower[algorithm]}: ${position.tickLower}`
208+
);
209+
console.log(
210+
`- ${DecodePositionsTickUpper[algorithm]}: ${position.tickUpper}`
211+
);
212+
console.log(
213+
`- ${DecodePositionsLiquidity[algorithm]}: ${position.liquidity}`
214+
);
215+
});
216+
217+
// Price data
218+
console.log('\nPrice data:');
219+
console.log(
220+
`- ${SqrtPrice[algorithm]}: ${integratorData.globalState.sqrtPriceX96}`
221+
);
222+
223+
console.log(
224+
"\nThis data can now be consumed by integrator's systems that expect UniswapV3 format"
225+
);
226+
}
227+
228+
// Mock in constants based on the provided code
229+
const Token0: { [key in AMMAlgorithm]: string } = {
230+
[AMMAlgorithm.UniswapV3]: 'token0',
231+
};
232+
233+
const Token1: { [key in AMMAlgorithm]: string } = {
234+
[AMMAlgorithm.UniswapV3]: 'token1',
235+
};
236+
237+
const SqrtPrice: { [key in AMMAlgorithm]: string } = {
238+
[AMMAlgorithm.UniswapV3]: 'sqrtPriceX96',
239+
};
240+
241+
const DecodePositionsLiquidity: { [key in AMMAlgorithm]: string | number } = {
242+
[AMMAlgorithm.UniswapV3]: 'liquidity',
243+
};
244+
245+
const DecodePositionsTickLower: { [key in AMMAlgorithm]: string | number } = {
246+
[AMMAlgorithm.UniswapV3]: 'tickLower',
247+
};
248+
249+
const DecodePositionsTickUpper: { [key in AMMAlgorithm]: string | number } = {
250+
[AMMAlgorithm.UniswapV3]: 'tickUpper',
251+
};
252+
253+
// Run the demo
254+
demonstrateCarbonIntegration().catch((error) => {
255+
console.error('Error in Carbon integration demo:', error);
256+
});
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "carbon-integration-demo",
3+
"version": "1.0.0",
4+
"main": "dist/demo.js",
5+
"license": "MIT",
6+
"scripts": {
7+
"build": "tsc",
8+
"start": "node dist/demo.js",
9+
"dev": "ts-node demo.ts"
10+
},
11+
"dependencies": {
12+
"@bancor/carbon-sdk": "latest",
13+
"ethers": "^5.7.2"
14+
},
15+
"devDependencies": {
16+
"@types/node": "^18.15.11",
17+
"ts-node": "^10.9.1",
18+
"typescript": "^5.0.4"
19+
}
20+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2020",
4+
"module": "commonjs",
5+
"declaration": true,
6+
"outDir": "./dist",
7+
"strict": true,
8+
"esModuleInterop": true,
9+
"skipLibCheck": true,
10+
"forceConsistentCasingInFileNames": true,
11+
"resolveJsonModule": true
12+
},
13+
"include": ["*.ts"],
14+
"exclude": ["node_modules", "dist"]
15+
}

0 commit comments

Comments
 (0)