@scalecrx/sdk 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +269 -0
- package/dist/constants.d.ts +8 -0
- package/dist/constants.js +10 -0
- package/dist/errors.d.ts +13 -0
- package/dist/errors.js +34 -0
- package/dist/idl/scale_amm.json +1471 -0
- package/dist/idl/scale_vmm.json +1425 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +29 -0
- package/dist/scale.d.ts +35 -0
- package/dist/scale.js +82 -0
- package/dist/scaleAmm.d.ts +68 -0
- package/dist/scaleAmm.js +465 -0
- package/dist/scaleVmm.d.ts +77 -0
- package/dist/scaleVmm.js +527 -0
- package/dist/types.d.ts +112 -0
- package/dist/types.js +2 -0
- package/dist/utils.d.ts +20 -0
- package/dist/utils.js +63 -0
- package/package.json +49 -0
package/dist/scaleAmm.js
ADDED
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ScaleSdkError = exports.ScaleAmm = void 0;
|
|
7
|
+
const anchor_1 = require("@coral-xyz/anchor");
|
|
8
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
9
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
10
|
+
const utils_1 = require("./utils");
|
|
11
|
+
const errors_1 = require("./errors");
|
|
12
|
+
Object.defineProperty(exports, "ScaleSdkError", { enumerable: true, get: function () { return errors_1.ScaleSdkError; } });
|
|
13
|
+
const scale_amm_json_1 = __importDefault(require("./idl/scale_amm.json"));
|
|
14
|
+
class ScaleAmm {
|
|
15
|
+
constructor(provider, programId, idlOverride, hasWallet = true) {
|
|
16
|
+
this.provider = provider;
|
|
17
|
+
this.programId = programId;
|
|
18
|
+
const resolvedIdl = idlOverride ?? scale_amm_json_1.default;
|
|
19
|
+
this.idl = { ...resolvedIdl, address: programId.toBase58() };
|
|
20
|
+
this.program = new anchor_1.Program(this.idl, provider);
|
|
21
|
+
this.idlErrors = (0, anchor_1.parseIdlErrors)(this.idl);
|
|
22
|
+
this.hasWallet = hasWallet;
|
|
23
|
+
}
|
|
24
|
+
getConfigAddress() {
|
|
25
|
+
return (0, utils_1.getConfigAddress)(this.programId);
|
|
26
|
+
}
|
|
27
|
+
getPoolAddress(owner, mintA, mintB) {
|
|
28
|
+
return (0, utils_1.getPoolAddress)(this.programId, owner, mintA, mintB);
|
|
29
|
+
}
|
|
30
|
+
getVaultAddress(pool, mint) {
|
|
31
|
+
return (0, utils_1.getVaultAddress)(this.programId, pool, mint);
|
|
32
|
+
}
|
|
33
|
+
async getPlatformConfig() {
|
|
34
|
+
const config = this.getConfigAddress();
|
|
35
|
+
try {
|
|
36
|
+
return await this.program.account.platformConfig.fetch(config);
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async getPlatformBaseToken() {
|
|
43
|
+
const config = await this.getPlatformConfig();
|
|
44
|
+
return config ? config.baseToken : null;
|
|
45
|
+
}
|
|
46
|
+
async getFeeBeneficiaries(poolInput) {
|
|
47
|
+
const pool = await this.resolvePool(poolInput);
|
|
48
|
+
return pool.data.feeBeneficiaries.slice(0, pool.data.feeBeneficiaryCount);
|
|
49
|
+
}
|
|
50
|
+
async getFeeShare(poolInput, wallet) {
|
|
51
|
+
const beneficiaries = await this.getFeeBeneficiaries(poolInput);
|
|
52
|
+
const entry = beneficiaries.find((beneficiary) => beneficiary.wallet.equals(wallet));
|
|
53
|
+
return entry ? entry.shareBps : 0;
|
|
54
|
+
}
|
|
55
|
+
async getTotalCreatorFeeBps(poolInput) {
|
|
56
|
+
const beneficiaries = await this.getFeeBeneficiaries(poolInput);
|
|
57
|
+
return beneficiaries.reduce((acc, beneficiary) => acc + beneficiary.shareBps, 0);
|
|
58
|
+
}
|
|
59
|
+
async getPool(poolOrAddress) {
|
|
60
|
+
const resolved = await this.resolvePool(poolOrAddress);
|
|
61
|
+
return resolved;
|
|
62
|
+
}
|
|
63
|
+
async getPoolByAddress(pool) {
|
|
64
|
+
try {
|
|
65
|
+
const data = (await this.program.account.pool.fetch(pool));
|
|
66
|
+
return {
|
|
67
|
+
address: pool,
|
|
68
|
+
owner: data.owner,
|
|
69
|
+
mintA: data.mintA,
|
|
70
|
+
mintB: data.mintB,
|
|
71
|
+
data,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
throw (0, errors_1.toSdkError)("getPoolByAddress failed", err, this.idlErrors);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async getPoolByMints(owner, mintA, mintB) {
|
|
79
|
+
const pool = this.getPoolAddress(owner, mintA, mintB);
|
|
80
|
+
return this.getPoolByAddress(pool);
|
|
81
|
+
}
|
|
82
|
+
async createPool(params, mintA, mintB, options = {}) {
|
|
83
|
+
const payer = options.payer ?? this.provider.wallet.publicKey;
|
|
84
|
+
const owner = options.owner ?? this.provider.wallet.publicKey;
|
|
85
|
+
const tokenWalletAuthority = options.tokenWalletAuthority ?? this.provider.wallet.publicKey;
|
|
86
|
+
try {
|
|
87
|
+
const { instructions, pool, vaultA, vaultB, signers } = await this.createPoolInstructions(params, mintA, mintB, options);
|
|
88
|
+
const tx = new web3_js_1.Transaction();
|
|
89
|
+
instructions.forEach((instruction) => tx.add(instruction));
|
|
90
|
+
const signature = await this.sendTransaction(tx, signers ?? [], "confirmed");
|
|
91
|
+
return { pool, vaultA, vaultB, signature };
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
throw (0, errors_1.toSdkError)("createPool failed", err, this.idlErrors);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async createPoolInstructions(params, mintA, mintB, options = {}) {
|
|
98
|
+
const payer = options.payer ?? this.provider.wallet.publicKey;
|
|
99
|
+
const owner = options.owner ?? this.provider.wallet.publicKey;
|
|
100
|
+
const tokenWalletAuthority = options.tokenWalletAuthority ?? this.provider.wallet.publicKey;
|
|
101
|
+
try {
|
|
102
|
+
const tokenProgramA = await (0, utils_1.getTokenProgramForMint)(this.provider.connection, mintA);
|
|
103
|
+
const tokenProgramB = await (0, utils_1.getTokenProgramForMint)(this.provider.connection, mintB);
|
|
104
|
+
const pool = this.getPoolAddress(owner, mintA, mintB);
|
|
105
|
+
const vaultA = this.getVaultAddress(pool, mintA);
|
|
106
|
+
const vaultB = this.getVaultAddress(pool, mintB);
|
|
107
|
+
const config = this.getConfigAddress();
|
|
108
|
+
let tokenWalletB = options.tokenWalletB;
|
|
109
|
+
const instructions = [];
|
|
110
|
+
if (!tokenWalletB) {
|
|
111
|
+
const ataResult = await (0, utils_1.maybeCreateAtaInstruction)(this.provider.connection, payer, tokenWalletAuthority, mintB, tokenProgramB);
|
|
112
|
+
tokenWalletB = ataResult.ata;
|
|
113
|
+
if (ataResult.instruction) {
|
|
114
|
+
instructions.push(ataResult.instruction);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const createParams = {
|
|
118
|
+
shift: (0, utils_1.toBN)(params.shift),
|
|
119
|
+
initialTokenBReserves: (0, utils_1.toBN)(params.initialTokenBReserves),
|
|
120
|
+
curve: params.curve,
|
|
121
|
+
feeBeneficiaries: params.feeBeneficiaries ?? [],
|
|
122
|
+
};
|
|
123
|
+
const ix = await this.program.methods
|
|
124
|
+
.create(createParams)
|
|
125
|
+
.accounts({
|
|
126
|
+
payer,
|
|
127
|
+
owner,
|
|
128
|
+
tokenWalletAuthority,
|
|
129
|
+
mintA,
|
|
130
|
+
mintB,
|
|
131
|
+
tokenWalletB,
|
|
132
|
+
pool,
|
|
133
|
+
vaultA,
|
|
134
|
+
vaultB,
|
|
135
|
+
tokenProgramA,
|
|
136
|
+
tokenProgramB,
|
|
137
|
+
systemProgram: web3_js_1.SystemProgram.programId,
|
|
138
|
+
config,
|
|
139
|
+
})
|
|
140
|
+
.instruction();
|
|
141
|
+
instructions.push(ix);
|
|
142
|
+
return { instructions, pool, vaultA, vaultB, signers: options.signers };
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
throw (0, errors_1.toSdkError)("createPoolInstructions failed", err, this.idlErrors);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
async createWithDevBuyInstructions(params, mintA, mintB, buyParams, options = {}) {
|
|
149
|
+
try {
|
|
150
|
+
const owner = options.owner ?? this.provider.wallet.publicKey;
|
|
151
|
+
const { instructions: createInstructions, pool, vaultA, vaultB, signers } = await this.createPoolInstructions(params, mintA, mintB, options);
|
|
152
|
+
const swapParams = { amount: (0, utils_1.toBN)(buyParams.amount), limit: (0, utils_1.toBN)(buyParams.limit) };
|
|
153
|
+
const user = this.provider.wallet.publicKey;
|
|
154
|
+
const autoCreateAta = options.autoCreateAta ?? true;
|
|
155
|
+
const wrapSol = options.wrapSol ?? true;
|
|
156
|
+
const unwrapSol = options.unwrapSol ?? false;
|
|
157
|
+
const tokenProgramA = await (0, utils_1.getTokenProgramForMint)(this.provider.connection, mintA);
|
|
158
|
+
const tokenProgramB = await (0, utils_1.getTokenProgramForMint)(this.provider.connection, mintB);
|
|
159
|
+
const preInstructions = [];
|
|
160
|
+
const postInstructions = [];
|
|
161
|
+
let userTaA = options.userTokenAccountA;
|
|
162
|
+
let userTaB = options.userTokenAccountB;
|
|
163
|
+
let createdAtaA = false;
|
|
164
|
+
if (!userTaA) {
|
|
165
|
+
const ataResult = await (0, utils_1.maybeCreateAtaInstruction)(this.provider.connection, user, user, mintA, tokenProgramA);
|
|
166
|
+
userTaA = ataResult.ata;
|
|
167
|
+
if (ataResult.instruction && !autoCreateAta) {
|
|
168
|
+
throw new Error(`Missing ATA for mintA: ${mintA.toBase58()}`);
|
|
169
|
+
}
|
|
170
|
+
if (ataResult.instruction) {
|
|
171
|
+
createdAtaA = true;
|
|
172
|
+
preInstructions.push(ataResult.instruction);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (!userTaB) {
|
|
176
|
+
const ataResult = await (0, utils_1.maybeCreateAtaInstruction)(this.provider.connection, user, user, mintB, tokenProgramB);
|
|
177
|
+
userTaB = ataResult.ata;
|
|
178
|
+
if (ataResult.instruction && !autoCreateAta) {
|
|
179
|
+
throw new Error(`Missing ATA for mintB: ${mintB.toBase58()}`);
|
|
180
|
+
}
|
|
181
|
+
if (ataResult.instruction) {
|
|
182
|
+
preInstructions.push(ataResult.instruction);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
const isNativeA = mintA.equals(spl_token_1.NATIVE_MINT);
|
|
186
|
+
if (isNativeA && wrapSol) {
|
|
187
|
+
preInstructions.push((0, utils_1.transferSolInstruction)(user, userTaA, swapParams.amount));
|
|
188
|
+
preInstructions.push((0, spl_token_1.createSyncNativeInstruction)(userTaA));
|
|
189
|
+
}
|
|
190
|
+
if (isNativeA && unwrapSol && createdAtaA) {
|
|
191
|
+
postInstructions.push((0, spl_token_1.createCloseAccountInstruction)(userTaA, user, user));
|
|
192
|
+
}
|
|
193
|
+
const config = this.getConfigAddress();
|
|
194
|
+
const configState = (await this.program.account.platformConfig.fetch(config));
|
|
195
|
+
const feeBeneficiary = configState.feeBeneficiary;
|
|
196
|
+
let platformFeeTaA = options.platformFeeTokenAccount;
|
|
197
|
+
if (!platformFeeTaA) {
|
|
198
|
+
const ataResult = await (0, utils_1.maybeCreateAtaInstruction)(this.provider.connection, user, feeBeneficiary, mintA, tokenProgramA, true);
|
|
199
|
+
platformFeeTaA = ataResult.ata;
|
|
200
|
+
if (ataResult.instruction && !autoCreateAta) {
|
|
201
|
+
throw new Error(`Missing platform fee ATA for mintA: ${mintA.toBase58()}`);
|
|
202
|
+
}
|
|
203
|
+
if (ataResult.instruction) {
|
|
204
|
+
preInstructions.push(ataResult.instruction);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
const beneficiaries = params.feeBeneficiaries ?? [];
|
|
208
|
+
if (options.beneficiaryTokenAccounts &&
|
|
209
|
+
options.beneficiaryTokenAccounts.length !== beneficiaries.length) {
|
|
210
|
+
throw new Error("beneficiaryTokenAccounts length mismatch");
|
|
211
|
+
}
|
|
212
|
+
const remainingAccounts = options.beneficiaryTokenAccounts ??
|
|
213
|
+
(await Promise.all(beneficiaries.map(async (beneficiary) => {
|
|
214
|
+
const ataResult = await (0, utils_1.maybeCreateAtaInstruction)(this.provider.connection, user, beneficiary.wallet, mintA, tokenProgramA, true);
|
|
215
|
+
if (ataResult.instruction && !autoCreateAta) {
|
|
216
|
+
throw new Error(`Missing beneficiary ATA for mintA: ${mintA.toBase58()}`);
|
|
217
|
+
}
|
|
218
|
+
if (ataResult.instruction) {
|
|
219
|
+
preInstructions.push(ataResult.instruction);
|
|
220
|
+
}
|
|
221
|
+
return ataResult.ata;
|
|
222
|
+
})));
|
|
223
|
+
const ix = await this.program.methods.buy(swapParams)
|
|
224
|
+
.accounts({
|
|
225
|
+
pool,
|
|
226
|
+
user,
|
|
227
|
+
owner,
|
|
228
|
+
mintA,
|
|
229
|
+
mintB,
|
|
230
|
+
userTaA,
|
|
231
|
+
userTaB,
|
|
232
|
+
vaultA,
|
|
233
|
+
vaultB,
|
|
234
|
+
platformFeeTaA,
|
|
235
|
+
tokenProgramA,
|
|
236
|
+
tokenProgramB,
|
|
237
|
+
systemProgram: web3_js_1.SystemProgram.programId,
|
|
238
|
+
config,
|
|
239
|
+
})
|
|
240
|
+
.remainingAccounts(remainingAccounts.map((pubkey) => ({
|
|
241
|
+
pubkey,
|
|
242
|
+
isWritable: true,
|
|
243
|
+
isSigner: false,
|
|
244
|
+
})))
|
|
245
|
+
.instruction();
|
|
246
|
+
return {
|
|
247
|
+
instructions: [...createInstructions, ...preInstructions, ix, ...postInstructions],
|
|
248
|
+
signers,
|
|
249
|
+
pool,
|
|
250
|
+
vaultA,
|
|
251
|
+
vaultB,
|
|
252
|
+
userTokenAccountA: userTaA,
|
|
253
|
+
userTokenAccountB: userTaB,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
catch (err) {
|
|
257
|
+
throw (0, errors_1.toSdkError)("createWithDevBuyInstructions failed", err, this.idlErrors);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
async buy(poolInput, params, options = {}) {
|
|
261
|
+
try {
|
|
262
|
+
const { instructions, signers } = await this.buyInstructions(poolInput, params, options);
|
|
263
|
+
const tx = new web3_js_1.Transaction();
|
|
264
|
+
instructions.forEach((instruction) => tx.add(instruction));
|
|
265
|
+
return await this.sendTransaction(tx, signers ?? [], "confirmed");
|
|
266
|
+
}
|
|
267
|
+
catch (err) {
|
|
268
|
+
throw (0, errors_1.toSdkError)("buy failed", err, this.idlErrors);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
async sell(poolInput, params, options = {}) {
|
|
272
|
+
try {
|
|
273
|
+
const { instructions, signers } = await this.sellInstructions(poolInput, params, options);
|
|
274
|
+
const tx = new web3_js_1.Transaction();
|
|
275
|
+
instructions.forEach((instruction) => tx.add(instruction));
|
|
276
|
+
return await this.sendTransaction(tx, signers ?? [], "confirmed");
|
|
277
|
+
}
|
|
278
|
+
catch (err) {
|
|
279
|
+
throw (0, errors_1.toSdkError)("sell failed", err, this.idlErrors);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
async buyInstructions(poolInput, params, options = {}) {
|
|
283
|
+
try {
|
|
284
|
+
const pool = await this.resolvePool(poolInput);
|
|
285
|
+
return await this.swapInstructions("buy", pool, params, options);
|
|
286
|
+
}
|
|
287
|
+
catch (err) {
|
|
288
|
+
throw (0, errors_1.toSdkError)("buyInstructions failed", err, this.idlErrors);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
async sellInstructions(poolInput, params, options = {}) {
|
|
292
|
+
try {
|
|
293
|
+
const pool = await this.resolvePool(poolInput);
|
|
294
|
+
return await this.swapInstructions("sell", pool, params, options);
|
|
295
|
+
}
|
|
296
|
+
catch (err) {
|
|
297
|
+
throw (0, errors_1.toSdkError)("sellInstructions failed", err, this.idlErrors);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
async estimateBuy(poolInput, params) {
|
|
301
|
+
return this.estimate("quoteBuy", poolInput, params);
|
|
302
|
+
}
|
|
303
|
+
async estimateSell(poolInput, params) {
|
|
304
|
+
return this.estimate("quoteSell", poolInput, params);
|
|
305
|
+
}
|
|
306
|
+
async estimate(method, poolInput, params) {
|
|
307
|
+
try {
|
|
308
|
+
const pool = await this.resolvePool(poolInput);
|
|
309
|
+
const swapParams = { amount: (0, utils_1.toBN)(params.amount), limit: (0, utils_1.toBN)(params.limit) };
|
|
310
|
+
const config = this.getConfigAddress();
|
|
311
|
+
const result = await this.program.methods[method](swapParams)
|
|
312
|
+
.accounts({
|
|
313
|
+
pool: pool.address,
|
|
314
|
+
owner: pool.owner,
|
|
315
|
+
mintA: pool.mintA,
|
|
316
|
+
mintB: pool.mintB,
|
|
317
|
+
config,
|
|
318
|
+
})
|
|
319
|
+
.view();
|
|
320
|
+
return {
|
|
321
|
+
newReservesA: result.newReservesA,
|
|
322
|
+
newReservesB: result.newReservesB,
|
|
323
|
+
amountA: result.amountA,
|
|
324
|
+
amountB: result.amountB,
|
|
325
|
+
feeA: result.feeA,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
catch (err) {
|
|
329
|
+
throw (0, errors_1.toSdkError)(`${method} failed`, err, this.idlErrors);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
async resolvePool(poolInput) {
|
|
333
|
+
if (poolInput instanceof web3_js_1.PublicKey) {
|
|
334
|
+
return this.getPoolByAddress(poolInput);
|
|
335
|
+
}
|
|
336
|
+
return this.getPoolByAddress(poolInput.address);
|
|
337
|
+
}
|
|
338
|
+
async swapInstructions(action, pool, params, options) {
|
|
339
|
+
const swapParams = { amount: (0, utils_1.toBN)(params.amount), limit: (0, utils_1.toBN)(params.limit) };
|
|
340
|
+
const user = this.provider.wallet.publicKey;
|
|
341
|
+
const autoCreateAta = options.autoCreateAta ?? true;
|
|
342
|
+
const wrapSol = options.wrapSol ?? action === "buy";
|
|
343
|
+
const unwrapSol = options.unwrapSol ?? action === "sell";
|
|
344
|
+
const tokenProgramA = await (0, utils_1.getTokenProgramForMint)(this.provider.connection, pool.mintA);
|
|
345
|
+
const tokenProgramB = await (0, utils_1.getTokenProgramForMint)(this.provider.connection, pool.mintB);
|
|
346
|
+
const preInstructions = [];
|
|
347
|
+
const postInstructions = [];
|
|
348
|
+
let userTaA = options.userTokenAccountA;
|
|
349
|
+
let userTaB = options.userTokenAccountB;
|
|
350
|
+
let createdAtaA = false;
|
|
351
|
+
if (!userTaA) {
|
|
352
|
+
const ataResult = await (0, utils_1.maybeCreateAtaInstruction)(this.provider.connection, user, user, pool.mintA, tokenProgramA);
|
|
353
|
+
userTaA = ataResult.ata;
|
|
354
|
+
if (ataResult.instruction && !autoCreateAta) {
|
|
355
|
+
throw new Error(`Missing ATA for mintA: ${pool.mintA.toBase58()}`);
|
|
356
|
+
}
|
|
357
|
+
if (ataResult.instruction) {
|
|
358
|
+
createdAtaA = true;
|
|
359
|
+
preInstructions.push(ataResult.instruction);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
if (!userTaB) {
|
|
363
|
+
const ataResult = await (0, utils_1.maybeCreateAtaInstruction)(this.provider.connection, user, user, pool.mintB, tokenProgramB);
|
|
364
|
+
userTaB = ataResult.ata;
|
|
365
|
+
if (ataResult.instruction && !autoCreateAta) {
|
|
366
|
+
throw new Error(`Missing ATA for mintB: ${pool.mintB.toBase58()}`);
|
|
367
|
+
}
|
|
368
|
+
if (ataResult.instruction) {
|
|
369
|
+
preInstructions.push(ataResult.instruction);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
const isNativeA = pool.mintA.equals(spl_token_1.NATIVE_MINT);
|
|
373
|
+
if (isNativeA && wrapSol) {
|
|
374
|
+
preInstructions.push((0, utils_1.transferSolInstruction)(user, userTaA, swapParams.amount));
|
|
375
|
+
preInstructions.push((0, spl_token_1.createSyncNativeInstruction)(userTaA));
|
|
376
|
+
}
|
|
377
|
+
if (isNativeA && unwrapSol && createdAtaA) {
|
|
378
|
+
postInstructions.push((0, spl_token_1.createCloseAccountInstruction)(userTaA, user, user));
|
|
379
|
+
}
|
|
380
|
+
const vaultA = this.getVaultAddress(pool.address, pool.mintA);
|
|
381
|
+
const vaultB = this.getVaultAddress(pool.address, pool.mintB);
|
|
382
|
+
const config = this.getConfigAddress();
|
|
383
|
+
const configState = (await this.program.account.platformConfig.fetch(config));
|
|
384
|
+
const feeBeneficiary = configState.feeBeneficiary;
|
|
385
|
+
let platformFeeTaA = options.platformFeeTokenAccount;
|
|
386
|
+
if (!platformFeeTaA) {
|
|
387
|
+
const ataResult = await (0, utils_1.maybeCreateAtaInstruction)(this.provider.connection, user, feeBeneficiary, pool.mintA, tokenProgramA, true);
|
|
388
|
+
platformFeeTaA = ataResult.ata;
|
|
389
|
+
if (ataResult.instruction && !autoCreateAta) {
|
|
390
|
+
throw new Error(`Missing platform fee ATA for mintA: ${pool.mintA.toBase58()}`);
|
|
391
|
+
}
|
|
392
|
+
if (ataResult.instruction) {
|
|
393
|
+
preInstructions.push(ataResult.instruction);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
const beneficiaries = pool.data.feeBeneficiaries.slice(0, pool.data.feeBeneficiaryCount);
|
|
397
|
+
if (options.beneficiaryTokenAccounts &&
|
|
398
|
+
options.beneficiaryTokenAccounts.length !== beneficiaries.length) {
|
|
399
|
+
throw new Error("beneficiaryTokenAccounts length mismatch");
|
|
400
|
+
}
|
|
401
|
+
const remainingAccounts = options.beneficiaryTokenAccounts ??
|
|
402
|
+
(await Promise.all(beneficiaries.map(async (beneficiary) => {
|
|
403
|
+
const ataResult = await (0, utils_1.maybeCreateAtaInstruction)(this.provider.connection, user, beneficiary.wallet, pool.mintA, tokenProgramA, true);
|
|
404
|
+
if (ataResult.instruction && !autoCreateAta) {
|
|
405
|
+
throw new Error(`Missing beneficiary ATA for mintA: ${pool.mintA.toBase58()}`);
|
|
406
|
+
}
|
|
407
|
+
if (ataResult.instruction) {
|
|
408
|
+
preInstructions.push(ataResult.instruction);
|
|
409
|
+
}
|
|
410
|
+
return ataResult.ata;
|
|
411
|
+
})));
|
|
412
|
+
const ix = await this.program.methods[action](swapParams)
|
|
413
|
+
.accounts({
|
|
414
|
+
pool: pool.address,
|
|
415
|
+
user,
|
|
416
|
+
owner: pool.owner,
|
|
417
|
+
mintA: pool.mintA,
|
|
418
|
+
mintB: pool.mintB,
|
|
419
|
+
userTaA,
|
|
420
|
+
userTaB,
|
|
421
|
+
vaultA,
|
|
422
|
+
vaultB,
|
|
423
|
+
platformFeeTaA,
|
|
424
|
+
tokenProgramA,
|
|
425
|
+
tokenProgramB,
|
|
426
|
+
systemProgram: web3_js_1.SystemProgram.programId,
|
|
427
|
+
config,
|
|
428
|
+
})
|
|
429
|
+
.remainingAccounts(remainingAccounts.map((pubkey) => ({
|
|
430
|
+
pubkey,
|
|
431
|
+
isWritable: true,
|
|
432
|
+
isSigner: false,
|
|
433
|
+
})))
|
|
434
|
+
.instruction();
|
|
435
|
+
const instructions = [...preInstructions, ix, ...postInstructions];
|
|
436
|
+
return {
|
|
437
|
+
instructions,
|
|
438
|
+
userTokenAccountA: userTaA,
|
|
439
|
+
userTokenAccountB: userTaB,
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
async sendTransaction(tx, signers = [], commitment) {
|
|
443
|
+
try {
|
|
444
|
+
if (!this.hasWallet) {
|
|
445
|
+
throw new errors_1.ScaleSdkError("No wallet provided. Direct execution requires an Anchor wallet.", "transaction failed", null);
|
|
446
|
+
}
|
|
447
|
+
if (!tx.feePayer) {
|
|
448
|
+
tx.feePayer = this.provider.wallet.publicKey;
|
|
449
|
+
}
|
|
450
|
+
const { blockhash, lastValidBlockHeight } = await this.provider.connection.getLatestBlockhash(commitment ?? "confirmed");
|
|
451
|
+
tx.recentBlockhash = blockhash;
|
|
452
|
+
if (signers.length) {
|
|
453
|
+
tx.partialSign(...signers);
|
|
454
|
+
}
|
|
455
|
+
const signedTx = await this.provider.wallet.signTransaction(tx);
|
|
456
|
+
const signature = await this.provider.connection.sendRawTransaction(signedTx.serialize(), { preflightCommitment: commitment });
|
|
457
|
+
await this.provider.connection.confirmTransaction({ signature, blockhash, lastValidBlockHeight }, commitment);
|
|
458
|
+
return signature;
|
|
459
|
+
}
|
|
460
|
+
catch (err) {
|
|
461
|
+
throw (0, errors_1.toSdkError)("transaction failed", err, this.idlErrors);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
exports.ScaleAmm = ScaleAmm;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { AnchorProvider, BN, Idl, Program } from "@coral-xyz/anchor";
|
|
2
|
+
import { PublicKey, TransactionInstruction } from "@solana/web3.js";
|
|
3
|
+
import { CreatePairInstructionResult, CreatePairOptions, CreatePairParamsInput, CurveTypeInput, CreatePairWithDevBuyInstructionResult, EstimateResult, PairAddress, PairRef, SwapInstructionResult, SwapParamsInput, VmmSwapOptions } from "./types";
|
|
4
|
+
import { ScaleSdkError } from "./errors";
|
|
5
|
+
export type PairAccount = {
|
|
6
|
+
enabled: boolean;
|
|
7
|
+
graduated: boolean;
|
|
8
|
+
mintA: PublicKey;
|
|
9
|
+
mintB: PublicKey;
|
|
10
|
+
tokenAReserves: BN;
|
|
11
|
+
tokenBReserves: BN;
|
|
12
|
+
shift: BN;
|
|
13
|
+
curve: CurveTypeInput;
|
|
14
|
+
bump: number;
|
|
15
|
+
feeBeneficiaryCount: number;
|
|
16
|
+
feeBeneficiaries: Array<{
|
|
17
|
+
wallet: PublicKey;
|
|
18
|
+
shareBps: number;
|
|
19
|
+
}>;
|
|
20
|
+
ammPool: PublicKey;
|
|
21
|
+
};
|
|
22
|
+
export declare class ScaleVmm {
|
|
23
|
+
readonly provider: AnchorProvider;
|
|
24
|
+
readonly programId: PublicKey;
|
|
25
|
+
readonly program: Program;
|
|
26
|
+
readonly idl: Idl;
|
|
27
|
+
readonly idlErrors: Map<number, string>;
|
|
28
|
+
readonly ammProgramId?: PublicKey;
|
|
29
|
+
readonly hasWallet: boolean;
|
|
30
|
+
constructor(provider: AnchorProvider, programId: PublicKey, idlOverride?: Idl, ammProgramId?: PublicKey, hasWallet?: boolean);
|
|
31
|
+
getConfigAddress(): PublicKey;
|
|
32
|
+
getPairAddress(mintA: PublicKey, mintB: PublicKey): PublicKey;
|
|
33
|
+
getVaultAddress(pair: PublicKey, mint: PublicKey): PublicKey;
|
|
34
|
+
getAmmPoolAddress(pair: PublicKey, mintA: PublicKey, mintB: PublicKey): PublicKey;
|
|
35
|
+
getAmmVaultAddress(pool: PublicKey, mint: PublicKey): PublicKey;
|
|
36
|
+
getPlatformConfig(): Promise<any>;
|
|
37
|
+
getPlatformConfigView(): Promise<any>;
|
|
38
|
+
getPlatformBaseToken(): Promise<PublicKey | null>;
|
|
39
|
+
getGraduationThreshold(): Promise<any>;
|
|
40
|
+
setGraduationThreshold(threshold: BN | number): Promise<string>;
|
|
41
|
+
setGraduationThresholdInstruction(threshold: BN | number): Promise<TransactionInstruction>;
|
|
42
|
+
getFeeBeneficiaries(pairInput: PairAddress | PairRef): Promise<{
|
|
43
|
+
wallet: PublicKey;
|
|
44
|
+
shareBps: number;
|
|
45
|
+
}[]>;
|
|
46
|
+
getFeeShare(pairInput: PairAddress | PairRef, wallet: PublicKey): Promise<number>;
|
|
47
|
+
getTotalCreatorFeeBps(pairInput: PairAddress | PairRef): Promise<number>;
|
|
48
|
+
getPair(pairOrAddress: PairAddress | PairRef): Promise<PairRef & {
|
|
49
|
+
data: PairAccount;
|
|
50
|
+
}>;
|
|
51
|
+
getPairByAddress(pair: PublicKey): Promise<PairRef & {
|
|
52
|
+
data: PairAccount;
|
|
53
|
+
}>;
|
|
54
|
+
getPairByMints(mintA: PublicKey, mintB: PublicKey): Promise<PairRef & {
|
|
55
|
+
data: PairAccount;
|
|
56
|
+
}>;
|
|
57
|
+
createPair(params: CreatePairParamsInput, mintA: PublicKey, mintB: PublicKey, options?: CreatePairOptions): Promise<{
|
|
58
|
+
pair: PublicKey;
|
|
59
|
+
vaultA: PublicKey;
|
|
60
|
+
vaultB: PublicKey;
|
|
61
|
+
signature: string;
|
|
62
|
+
}>;
|
|
63
|
+
createPairInstructions(params: CreatePairParamsInput, mintA: PublicKey, mintB: PublicKey, options?: CreatePairOptions): Promise<CreatePairInstructionResult>;
|
|
64
|
+
createWithDevBuyInstructions(params: CreatePairParamsInput, mintA: PublicKey, mintB: PublicKey, buyParams: SwapParamsInput, options?: (CreatePairOptions & VmmSwapOptions)): Promise<CreatePairWithDevBuyInstructionResult>;
|
|
65
|
+
buy(pairInput: PairAddress | PairRef, params: SwapParamsInput, options?: VmmSwapOptions): Promise<string>;
|
|
66
|
+
sell(pairInput: PairAddress | PairRef, params: SwapParamsInput, options?: VmmSwapOptions): Promise<string>;
|
|
67
|
+
buyInstructions(pairInput: PairAddress | PairRef, params: SwapParamsInput, options?: VmmSwapOptions): Promise<SwapInstructionResult>;
|
|
68
|
+
sellInstructions(pairInput: PairAddress | PairRef, params: SwapParamsInput, options?: VmmSwapOptions): Promise<SwapInstructionResult>;
|
|
69
|
+
estimateBuy(pairInput: PairAddress | PairRef, params: SwapParamsInput): Promise<EstimateResult>;
|
|
70
|
+
estimateSell(pairInput: PairAddress | PairRef, params: SwapParamsInput): Promise<EstimateResult>;
|
|
71
|
+
private estimate;
|
|
72
|
+
private resolvePair;
|
|
73
|
+
private swapInstructions;
|
|
74
|
+
private resolveAmmProgramId;
|
|
75
|
+
private sendTransaction;
|
|
76
|
+
}
|
|
77
|
+
export { ScaleSdkError };
|