forked from freedevm/reflection_solana
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdistribute.js
More file actions
237 lines (207 loc) · 7.26 KB
/
distribute.js
File metadata and controls
237 lines (207 loc) · 7.26 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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
import * as anchor from '@coral-xyz/anchor';
import { Program } from '@coral-xyz/anchor';
import { PublicKey, Connection, Keypair, Transaction } from '@solana/web3.js';
import { TokenFeeReflector } from './types/token_fee_reflector'; // This would be generated by anchor build
import {
createAssociatedTokenAccountInstruction,
getAssociatedTokenAddress,
TOKEN_PROGRAM_ID,
} from '@solana/spl-token';
import fetch from 'node-fetch';
// Jupiter API endpoints
const JUPITER_QUOTE_API = 'https://quote-api.jup.ag/v6/quote';
const JUPITER_SWAP_API = 'https://quote-api.jup.ag/v6/swap';
// Initialize anchor and connection
const connection = new Connection('https://api.mainnet-beta.solana.com', 'confirmed');
const wallet = new anchor.Wallet(Keypair.generate()); // Replace with your own wallet
const provider = new anchor.AnchorProvider(connection, wallet, {
commitment: 'confirmed',
});
anchor.setProvider(provider);
// Program ID from the deployed contract
const programId = new PublicKey('YourProgramIdHere11111111111111111111111111111111');
const program = new Program<TokenFeeReflector>(
require('./target/idl/token_fee_reflector.json'),
programId
);
/**
* Initialize the fee distributor
*/
async function initialize() {
const feeDistributor = anchor.web3.Keypair.generate();
await program.rpc.initialize({
accounts: {
feeDistributor: feeDistributor.publicKey,
deployer: wallet.publicKey,
authority: wallet.publicKey,
systemProgram: anchor.web3.SystemProgram.programId,
},
signers: [feeDistributor],
});
console.log('Fee distributor initialized:', feeDistributor.publicKey.toString());
return feeDistributor.publicKey;
}
/**
* Get Jupiter quote for a token swap
*/
async function getJupiterQuote(
inputMint: string,
outputMint: string,
amount: number,
slippageBps: number = 50
) {
const params = new URLSearchParams({
inputMint,
outputMint,
amount: amount.toString(),
slippageBps: slippageBps.toString(),
});
const response = await fetch(`${JUPITER_QUOTE_API}?${params.toString()}`);
return await response.json();
}
/**
* Get Jupiter swap transaction
*/
async function getJupiterSwapTransaction(
quoteResponse: any,
userPublicKey: string
) {
const response = await fetch(JUPITER_SWAP_API, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
quoteResponse,
userPublicKey,
wrapUnwrapSOL: true,
}),
});
return await response.json();
}
/**
* Get token holders data
* In a real implementation, you would fetch this from your token contract or an indexer
*/
async function getTokenHolders(tokenMint: PublicKey): Promise<[PublicKey, number][]> {
// This is a placeholder - you would get this data from your token contract or indexer
return [
[new PublicKey('11111111111111111111111111111111'), 100000],
[new PublicKey('22222222222222222222222222222222'), 200000],
[new PublicKey('33333333333333333333333333333333'), 300000],
];
}
/**
* Main function to swap and distribute tokens
*/
async function swapAndDistribute(
feeDistributorPubkey: PublicKey,
feeTokenMint: PublicKey,
amount: number
) {
// Get token holders
const holders = await getTokenHolders(feeTokenMint);
// Token accounts for different days
const token1Mint = new PublicKey('Token1MintAddress111111111111111111111111111');
const token2Mint = new PublicKey('Token2MintAddress111111111111111111111111111');
const token3Mint = new PublicKey('Token3MintAddress111111111111111111111111111');
const token4Mint = new PublicKey('Token4MintAddress111111111111111111111111111');
const token5Mint = new PublicKey('Token5MintAddress111111111111111111111111111');
const token6Mint = new PublicKey('Token6MintAddress111111111111111111111111111');
const token7Mint = new PublicKey('Token7MintAddress111111111111111111111111111');
const wbtcMint = new PublicKey('WBTCMintAddress1111111111111111111111111111');
const solReserveMint = new PublicKey('SOLMintAddress11111111111111111111111111111');
// Find token accounts
const feeTokenAccount = await getAssociatedTokenAddress(
feeTokenMint,
wallet.publicKey
);
const token1Account = await getAssociatedTokenAddress(
token1Mint,
wallet.publicKey,
true // Allow owner off curve
);
const token2Account = await getAssociatedTokenAddress(
token2Mint,
wallet.publicKey,
true
);
// ... find other token accounts similarly
// Get Jupiter accounts and instructions
// This is a simplification - you would need to properly integrate with Jupiter's API
const jupiterProgramId = new PublicKey('JUP6LkbZbjS1jKKwapdHbFPCynZi3');
// Get the current day's target token mint
const currentDay = Math.floor(Date.now() / 86400000) % 7;
let targetTokenMint: PublicKey;
switch (currentDay) {
case 0: targetTokenMint = token1Mint; break;
case 1: targetTokenMint = token2Mint; break;
case 2: targetTokenMint = token3Mint; break;
case 3: targetTokenMint = token4Mint; break;
case 4: targetTokenMint = token5Mint; break;
case 5: targetTokenMint = token6Mint; break;
case 6: targetTokenMint = token7Mint; break;
default: targetTokenMint = token1Mint;
}
// Get Jupiter quote for the swap
const quote = await getJupiterQuote(
feeTokenMint.toString(),
targetTokenMint.toString(),
amount
);
// Get Jupiter swap transaction
const swapTransaction = await getJupiterSwapTransaction(
quote,
wallet.publicKey.toString()
);
// Extract accounts and instruction data from Jupiter's response
// This would require parsing the transaction instructions from Jupiter
const jupiterAccounts = []; // This would be populated from swapTransaction
// Call the program
await program.rpc.swapAndDistribute(
new anchor.BN(amount),
holders.map(([pubkey, balance]) => [pubkey, new anchor.BN(balance)]),
{
accounts: {
feeDistributor: feeDistributorPubkey,
feeTokenAccount,
wbtcAccount: await getAssociatedTokenAddress(wbtcMint, wallet.publicKey),
programTokenAccount: await getAssociatedTokenAddress(programId, wallet.publicKey, true),
solReserveAccount: await getAssociatedTokenAddress(solReserveMint, wallet.publicKey),
token1Account,
token2Account,
// ... other token accounts
deployer: wallet.publicKey,
admin: wallet.publicKey,
authority: wallet.publicKey,
jupiterProgram: jupiterProgramId,
tokenProgram: TOKEN_PROGRAM_ID,
},
remainingAccounts: [
// Add holder accounts
...holders.map(([pubkey, _]) => ({
pubkey,
isWritable: true,
isSigner: false,
})),
// Add Jupiter accounts
...jupiterAccounts,
],
}
);
console.log('Swap and distribute completed!');
}
// Example usage
async function main() {
try {
const feeDistributorPubkey = await initialize();
// Example fee token mint
const feeTokenMint = new PublicKey('FeeTokenMint1111111111111111111111111111');
// Example amount to swap and distribute
const amount = 1000000; // Adjust based on your token's decimals
await swapAndDistribute(feeDistributorPubkey, feeTokenMint, amount);
} catch (error) {
console.error('Error:', error);
}
}
main();