yamaswap-sdk
Version:
ETF SDK for Solana and Evm
1,503 lines (1,495 loc) • 38.9 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/core/client.ts
var client_exports = {};
__export(client_exports, {
DexClient: () => DexClient
});
module.exports = __toCommonJS(client_exports);
var anchor2 = __toESM(require("@coral-xyz/anchor"));
var import_web33 = require("@solana/web3.js");
// src/idl/iswap.json
var iswap_default = {
address: "dXgZyuguvD2m5G5385XkdokZBryUoSE6LbNJeWiFiN5",
metadata: {
name: "iswap",
version: "0.1.0",
spec: "0.1.0",
description: "Created with Anchor"
},
instructions: [
{
name: "close",
discriminator: [
98,
165,
201,
177,
108,
65,
206,
96
],
accounts: [
{
name: "payer",
writable: true,
signer: true
},
{
name: "iswap",
writable: true
}
],
args: []
},
{
name: "decrement",
discriminator: [
106,
227,
168,
59,
248,
27,
150,
101
],
accounts: [
{
name: "iswap",
writable: true
}
],
args: []
},
{
name: "etf_burn",
discriminator: [
185,
203,
114,
195,
129,
70,
235,
23
],
accounts: [
{
name: "etf_token_info",
pda: {
seeds: [
{
kind: "const",
value: [
101,
116,
102,
95,
116,
111,
107,
101,
110,
95,
118,
51
]
},
{
kind: "account",
path: "etf_token_mint_account"
}
]
}
},
{
name: "etf_token_mint_account",
writable: true
},
{
name: "etf_token_ata",
writable: true,
pda: {
seeds: [
{
kind: "account",
path: "authority"
},
{
kind: "const",
value: [
6,
221,
246,
225,
215,
101,
161,
147,
217,
203,
225,
70,
206,
235,
121,
172,
28,
180,
133,
237,
95,
91,
55,
145,
58,
140,
245,
133,
126,
255,
0,
169
]
},
{
kind: "account",
path: "etf_token_mint_account"
}
],
program: {
kind: "const",
value: [
140,
151,
37,
143,
78,
36,
137,
241,
187,
61,
16,
41,
20,
142,
13,
131,
11,
90,
19,
153,
218,
255,
16,
132,
4,
142,
123,
216,
219,
233,
248,
89
]
}
}
},
{
name: "authority",
writable: true,
signer: true
},
{
name: "token_program"
},
{
name: "associated_token_program",
address: "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"
},
{
name: "system_program",
address: "11111111111111111111111111111111"
}
],
args: [
{
name: "lamports",
type: "f64"
}
]
},
{
name: "etf_create",
discriminator: [
0,
81,
62,
85,
242,
37,
4,
245
],
accounts: [
{
name: "etf_token_info",
writable: true,
pda: {
seeds: [
{
kind: "const",
value: [
101,
116,
102,
95,
116,
111,
107,
101,
110,
95,
118,
51
]
},
{
kind: "account",
path: "etf_token_mint_account"
}
]
}
},
{
name: "metadata_account",
writable: true,
pda: {
seeds: [
{
kind: "const",
value: [
109,
101,
116,
97,
100,
97,
116,
97
]
},
{
kind: "account",
path: "token_metadata_program"
},
{
kind: "account",
path: "etf_token_mint_account"
}
],
program: {
kind: "account",
path: "token_metadata_program"
}
}
},
{
name: "etf_token_mint_account",
writable: true,
pda: {
seeds: [
{
kind: "const",
value: [
101,
116,
102,
95,
116,
111,
107,
101,
110,
95,
118,
51
]
},
{
kind: "arg",
path: "args.symbol"
}
]
}
},
{
name: "rent",
address: "SysvarRent111111111111111111111111111111111"
},
{
name: "authority",
writable: true,
signer: true
},
{
name: "token_metadata_program",
address: "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
},
{
name: "token_program",
address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
},
{
name: "system_program",
address: "11111111111111111111111111111111"
}
],
args: [
{
name: "args",
type: {
defined: {
name: "EtfTokenArgs"
}
}
}
]
},
{
name: "etf_mint",
discriminator: [
253,
102,
37,
173,
154,
46,
245,
224
],
accounts: [
{
name: "etf_token_info",
pda: {
seeds: [
{
kind: "const",
value: [
101,
116,
102,
95,
116,
111,
107,
101,
110,
95,
118,
51
]
},
{
kind: "account",
path: "etf_token_mint_account"
}
]
}
},
{
name: "etf_token_mint_account",
writable: true
},
{
name: "etf_token_ata",
writable: true,
pda: {
seeds: [
{
kind: "account",
path: "authority"
},
{
kind: "const",
value: [
6,
221,
246,
225,
215,
101,
161,
147,
217,
203,
225,
70,
206,
235,
121,
172,
28,
180,
133,
237,
95,
91,
55,
145,
58,
140,
245,
133,
126,
255,
0,
169
]
},
{
kind: "account",
path: "etf_token_mint_account"
}
],
program: {
kind: "const",
value: [
140,
151,
37,
143,
78,
36,
137,
241,
187,
61,
16,
41,
20,
142,
13,
131,
11,
90,
19,
153,
218,
255,
16,
132,
4,
142,
123,
216,
219,
233,
248,
89
]
}
}
},
{
name: "authority",
writable: true,
signer: true
},
{
name: "token_program"
},
{
name: "associated_token_program",
address: "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"
},
{
name: "system_program",
address: "11111111111111111111111111111111"
}
],
args: [
{
name: "lamports",
type: "f64"
}
]
},
{
name: "increment",
discriminator: [
11,
18,
104,
9,
104,
174,
59,
33
],
accounts: [
{
name: "iswap",
writable: true
}
],
args: []
},
{
name: "initialize",
discriminator: [
175,
175,
109,
31,
13,
152,
155,
237
],
accounts: [
{
name: "payer",
writable: true,
signer: true
},
{
name: "iswap",
writable: true,
signer: true
},
{
name: "system_program",
address: "11111111111111111111111111111111"
}
],
args: []
},
{
name: "initialize_user",
discriminator: [
111,
17,
185,
250,
60,
122,
38,
254
],
accounts: [
{
name: "user_account",
writable: true,
pda: {
seeds: [
{
kind: "const",
value: [
117,
115,
101,
114,
65,
99,
99,
111,
117,
110,
116,
95,
118,
50
]
},
{
kind: "account",
path: "user"
}
]
}
},
{
name: "inviter_account",
optional: true
},
{
name: "user",
writable: true,
signer: true
},
{
name: "system_program",
address: "11111111111111111111111111111111"
}
],
args: [
{
name: "nickname",
type: "string"
},
{
name: "direct_inviter",
type: {
option: "pubkey"
}
},
{
name: "avatar",
type: "string"
}
]
},
{
name: "set",
discriminator: [
198,
51,
53,
241,
116,
29,
126,
194
],
accounts: [
{
name: "iswap",
writable: true
}
],
args: [
{
name: "value",
type: "u8"
}
]
}
],
accounts: [
{
name: "EtfToken",
discriminator: [
187,
90,
26,
73,
137,
112,
105,
60
]
},
{
name: "Iswap",
discriminator: [
228,
5,
227,
43,
35,
87,
170,
87
]
},
{
name: "UserAccount",
discriminator: [
211,
33,
136,
16,
186,
110,
242,
127
]
}
],
events: [
{
name: "EtfTokenBurnEvent",
discriminator: [
86,
32,
4,
35,
170,
93,
29,
251
]
},
{
name: "EtfTokenCreateEvent",
discriminator: [
166,
238,
215,
49,
221,
120,
90,
191
]
},
{
name: "EtfTokenMintEvent",
discriminator: [
55,
168,
3,
194,
101,
86,
242,
173
]
},
{
name: "UserInitialized",
discriminator: [
66,
195,
5,
223,
42,
84,
135,
60
]
}
],
errors: [
{
code: 6e3,
name: "InvalidAccounts",
msg: "Lack of necessary accounts"
},
{
code: 6001,
name: "InsufficientBalance",
msg: "Insufficient balance"
}
],
types: [
{
name: "EtfAsset",
type: {
kind: "struct",
fields: [
{
name: "token",
type: "pubkey"
},
{
name: "weight",
type: "u16"
}
]
}
},
{
name: "EtfToken",
type: {
kind: "struct",
fields: [
{
name: "mint_account",
type: "pubkey"
},
{
name: "creator",
type: "pubkey"
},
{
name: "create_at",
type: "i64"
},
{
name: "description",
type: "string"
},
{
name: "assets",
type: {
vec: {
defined: {
name: "EtfAsset"
}
}
}
}
]
}
},
{
name: "EtfTokenArgs",
type: {
kind: "struct",
fields: [
{
name: "name",
type: "string"
},
{
name: "symbol",
type: "string"
},
{
name: "description",
type: "string"
},
{
name: "url",
type: "string"
},
{
name: "assets",
type: {
vec: {
defined: {
name: "EtfAsset"
}
}
}
}
]
}
},
{
name: "EtfTokenBurnEvent",
type: {
kind: "struct",
fields: [
{
name: "etf_token_mint",
type: "pubkey"
},
{
name: "authority",
type: "pubkey"
},
{
name: "lamports",
type: "f64"
}
]
}
},
{
name: "EtfTokenCreateEvent",
type: {
kind: "struct",
fields: [
{
name: "etf_token_mint",
type: "pubkey"
},
{
name: "creator",
type: "pubkey"
}
]
}
},
{
name: "EtfTokenMintEvent",
type: {
kind: "struct",
fields: [
{
name: "etf_token_mint",
type: "pubkey"
},
{
name: "authority",
type: "pubkey"
},
{
name: "lamports",
type: "f64"
}
]
}
},
{
name: "Iswap",
type: {
kind: "struct",
fields: [
{
name: "count",
type: "u8"
}
]
}
},
{
name: "UserAccount",
type: {
kind: "struct",
fields: [
{
name: "owner",
type: "pubkey"
},
{
name: "is_frozen",
type: "bool"
},
{
name: "created_at",
type: "i64"
},
{
name: "inviter_code",
type: {
option: "pubkey"
}
},
{
name: "direct_inviter",
type: {
option: "pubkey"
}
},
{
name: "nickname",
type: "string"
},
{
name: "avatar",
type: "string"
},
{
name: "padding",
type: {
array: [
"u64",
10
]
}
}
]
}
},
{
name: "UserInitialized",
type: {
kind: "struct",
fields: [
{
name: "user",
type: "pubkey"
},
{
name: "inviter_code",
type: {
option: "pubkey"
}
},
{
name: "nickname",
type: "string"
},
{
name: "created_at",
type: "i64"
}
]
}
}
]
};
// src/utils/getAddress.ts
var anchor = __toESM(require("@coral-xyz/anchor"));
var import_web3 = require("@solana/web3.js");
function deriveEtfTokenMintAccount(program, seeds) {
const buffers = seeds.map((part) => {
if (typeof part === "string") {
return Buffer.from(part);
} else if (part instanceof import_web3.PublicKey) {
return part.toBuffer();
} else {
throw new Error(`Unsupported type in symbolParts: ${typeof part}`);
}
});
return anchor.web3.PublicKey.findProgramAddressSync(
[
...buffers
],
program.programId
);
}
// src/utils/checks.ts
var import_web32 = require("@solana/web3.js");
var import_spl_token = require("@solana/spl-token");
// src/utils/error.ts
var DexSDKError = class _DexSDKError extends Error {
constructor(message) {
super(message);
this.name = "DexSDKError";
Object.setPrototypeOf(this, _DexSDKError.prototype);
}
};
var ETFNotExistsError = class _ETFNotExistsError extends DexSDKError {
constructor(message) {
super(message);
this.name = "ETFNotExistsError";
Object.setPrototypeOf(this, _ETFNotExistsError.prototype);
}
};
var ETFInsufficientBalanceError = class _ETFInsufficientBalanceError extends DexSDKError {
constructor(message) {
super(message);
this.name = "ETFInsufficientBalanceError";
Object.setPrototypeOf(this, _ETFInsufficientBalanceError.prototype);
}
};
var ETFInvalidParamsError = class _ETFInvalidParamsError extends DexSDKError {
constructor(message) {
super(message);
this.name = "ETFInvalidParamsError";
Object.setPrototypeOf(this, _ETFInvalidParamsError.prototype);
}
};
// src/utils/checks.ts
async function checkATAExists(client, tokens, owner, isContract = false) {
for (const token of tokens) {
const tokenAccountAddress = (0, import_spl_token.getAssociatedTokenAddressSync)(token, owner, isContract);
try {
return await (0, import_spl_token.getAccount)(client.connection, tokenAccountAddress);
} catch (e) {
if (e instanceof import_spl_token.TokenAccountNotFoundError) {
throw new import_spl_token.TokenAccountNotFoundError(`\u8D26\u6237 ${tokenAccountAddress.toBase58()} \u4E0D\u5B58\u5728`);
}
throw e;
}
}
return void 0;
}
async function checkBalance(client, etfAddress, owner, requiredAmount) {
const balance = await client.queries.getETFBalance(etfAddress, owner);
if (balance < requiredAmount) {
throw new ETFInsufficientBalanceError(`\u7528\u6237\u4EE3\u5E01\u8D26\u6237\u4F59\u989D\u4E0D\u8DB3\uFF0C\u6240\u9700: ${requiredAmount}, \u5F53\u524D: ${balance}`);
}
}
async function checkETFExists(client, etfAddress) {
const etfInfo = await client.queries.getETFInfo(etfAddress);
if (typeof etfInfo === "string") {
throw new ETFNotExistsError(etfInfo);
}
return etfInfo;
}
function validateETFCreateParams(params) {
const { assets } = params;
if (!assets?.length) {
throw new ETFInvalidParamsError("ETF\u7EC4\u6210\u90E8\u5206\u4E0D\u80FD\u4E3A\u7A7A");
}
const totalWeight = assets.reduce((sum, item) => sum + item.weight, 0);
if (totalWeight !== 100) {
throw new ETFInvalidParamsError(`ETF\u7EC4\u6210\u90E8\u5206\u6743\u91CD\u4E4B\u548C\u5FC5\u987B\u4E3A100\uFF0C\u5F53\u524D\u4E3A: ${totalWeight}`);
}
const tokenSet = /* @__PURE__ */ new Set();
for (const item of assets) {
let tokenKey;
try {
tokenKey = new import_web32.PublicKey(item.token);
} catch (e) {
throw new ETFInvalidParamsError(`\u65E0\u6548\u7684\u4EE3\u5E01\u5730\u5740: ${item.token}`);
}
if (tokenSet.has(tokenKey.toBase58())) {
throw new ETFInvalidParamsError(`\u5B58\u5728\u91CD\u590D\u7684\u4EE3\u5E01\u5730\u5740: ${item.token}`);
}
tokenSet.add(tokenKey.toBase58());
if (item.weight <= 0) {
throw new ETFInvalidParamsError(`\u4EE3\u5E01\u6743\u91CD\u5FC5\u987B\u5927\u4E8E0: ${item.token}`);
}
}
}
function validateMintETFParams(params) {
if (params.lamports <= 0) {
throw new ETFInvalidParamsError("\u8D2D\u4E70\u4EFD\u989D\u5FC5\u987B\u5927\u4E8E0");
}
if (params.lamports > 1e15) {
throw new ETFInvalidParamsError("\u8D2D\u4E70\u4EFD\u989D\u8D85\u8FC7\u6700\u5927\u9650\u5236\uFF081000000 SOL\uFF09");
}
}
// src/utils/queries.ts
var ETFQueries = class {
constructor(client) {
this.client = client;
}
async getETFInfo(etfAddress) {
const [etfInfoAddress] = deriveEtfTokenMintAccount(this.client.program, ["etf_token_v3", etfAddress]);
try {
const etfInfo = await this.client.program.account.etfToken.fetch(etfInfoAddress);
return {
etfCoreAddress: etfInfoAddress,
creator: etfInfo.creator.toString(),
description: etfInfo.description,
assets: etfInfo.assets.map((item) => ({
token: item.token,
weight: item.weight
}))
};
} catch (error) {
if (error instanceof Error && error.message.includes("Account does not exist")) {
return `ETF\u4E0D\u5B58\u5728: ${etfAddress}`;
}
throw error;
}
}
async getETFBalance(etfAddress, ownerAddress) {
try {
const tokenAccount = await checkATAExists(this.client, [etfAddress], ownerAddress);
return Number(tokenAccount?.amount);
} catch (error) {
if (error instanceof Error && error.message.includes("Account does not exist")) {
return 0;
}
throw error;
}
}
};
// src/core/client.ts
var import_spl_token2 = require("@solana/spl-token");
var DexClient = class {
constructor(connection, wallet, provider) {
this.connection = connection;
this.connection = connection;
this.wallet = wallet;
this.program = new anchor2.Program(iswap_default, provider);
this.queries = new ETFQueries(this);
}
async createETF(params) {
try {
validateETFCreateParams(params);
const { name, symbol, description, url, assets } = params;
const [etfAddress] = deriveEtfTokenMintAccount(this.program, ["etf_token_v3", symbol]);
const [etfCoreAddress] = deriveEtfTokenMintAccount(this.program, ["etf_token_v3", etfAddress]);
const etfInfo = await this.queries.getETFInfo(etfAddress);
if (typeof etfInfo !== "string") {
return {
success: false,
error: "etf already exists",
data: {
etfAddress,
etfCoreAddress: etfInfo.etfCoreAddress,
symbol,
description: etfInfo.description,
creator: etfInfo.creator,
assets: etfInfo.assets
}
};
}
const latestBlockhash = await this.connection.getLatestBlockhash("confirmed");
console.log("get the latest blockhash:", latestBlockhash.blockhash);
let tx = new import_web33.Transaction();
for (const { token } of assets) {
const tokenKey = new import_web33.PublicKey(token);
const address = (0, import_spl_token2.getAssociatedTokenAddressSync)(tokenKey, etfCoreAddress, true);
try {
await (0, import_spl_token2.getAccount)(this.connection, address);
} catch (e) {
if (e instanceof import_spl_token2.TokenAccountNotFoundError) {
tx.add(
(0, import_spl_token2.createAssociatedTokenAccountInstruction)(
this.wallet.publicKey,
address,
etfCoreAddress,
tokenKey
)
);
}
}
}
const ix = await this.program.methods.etfCreate({
name,
symbol,
description,
url,
assets: assets.map((c) => ({
token: new import_web33.PublicKey(c.token),
weight: c.weight
}))
}).transaction();
tx.add(ix);
tx.recentBlockhash = latestBlockhash.blockhash;
tx.feePayer = this.wallet.publicKey;
console.log("transaction created:", {
recentBlockhash: tx.recentBlockhash,
feePayer: tx.feePayer.toBase58(),
instructions: tx.instructions.length
});
try {
const signedTx = await this.wallet.signTransaction(tx);
console.log("transaction signed");
const txid = await this.connection.sendRawTransaction(signedTx.serialize(), {
skipPreflight: false,
preflightCommitment: "confirmed",
maxRetries: 5
});
console.log("transaction sent, signed:", txid);
const confirmation = await this.connection.confirmTransaction({
signature: txid,
blockhash: latestBlockhash.blockhash,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
}, "confirmed");
if (confirmation.value.err) {
throw new Error(`transaction confirm failed: ${JSON.stringify(confirmation.value.err)}`);
}
console.log("transaction confirmed");
const confirmedEtfInfo = await this.queries.getETFInfo(etfAddress);
if (typeof confirmedEtfInfo === "string") {
throw new Error("etf create success but not found etf info");
}
return {
success: true,
txid,
data: {
etfAddress,
etfCoreAddress,
symbol,
name,
description,
creator: confirmedEtfInfo.creator,
assets: confirmedEtfInfo.assets
}
};
} catch (error) {
console.error("createETF error:", error);
throw error;
}
} catch (error) {
console.error("Error details:", error);
if (error instanceof Error) {
console.error("Error stack:", error.stack);
}
return {
success: false,
txid: "",
error: error instanceof Error ? error.message : "meet an unknown error when create ETF"
};
}
}
async purchaseETF(params) {
try {
const etfAddress = new import_web33.PublicKey(params.etfAddress);
validateMintETFParams(params);
const etfInfo = await checkETFExists(this, etfAddress);
await checkATAExists(this, etfInfo.assets.map((item) => item.token), this.wallet.publicKey);
await checkATAExists(this, etfInfo.assets.map((item) => item.token), etfInfo.etfCoreAddress, true);
const latestBlockhash = await this.connection.getLatestBlockhash("confirmed");
console.log("get the latest blockhash:", latestBlockhash.blockhash);
const remainingAccounts = [];
for (const item of etfInfo.assets) {
const userATA = (0, import_spl_token2.getAssociatedTokenAddressSync)(item.token, this.wallet.publicKey);
const contractATA = (0, import_spl_token2.getAssociatedTokenAddressSync)(item.token, etfInfo.etfCoreAddress, true);
remainingAccounts.push(
{ pubkey: userATA, isSigner: false, isWritable: true },
{ pubkey: contractATA, isSigner: false, isWritable: true },
{ pubkey: item.token, isSigner: false, isWritable: false }
// 添加代币Mint账户
);
}
const splTokenProgramId = new import_web33.PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
const splToken2022ProgramId = new import_web33.PublicKey("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb");
remainingAccounts.push(
{ pubkey: splTokenProgramId, isSigner: false, isWritable: false },
{ pubkey: splToken2022ProgramId, isSigner: false, isWritable: false }
);
console.log(remainingAccounts);
const ix = await this.program.methods.etfMint(params.lamports).accounts({
etfTokenMintAccount: params.etfAddress,
authority: this.wallet.publicKey,
tokenProgram: splTokenProgramId
}).remainingAccounts(remainingAccounts).transaction();
const modifyComputeUnits = anchor2.web3.ComputeBudgetProgram.setComputeUnitLimit({
units: 4e5
});
let tx = new import_web33.Transaction().add(ix).add(modifyComputeUnits);
tx.recentBlockhash = latestBlockhash.blockhash;
tx.feePayer = this.wallet.publicKey;
console.log("transaction created:", {
recentBlockhash: tx.recentBlockhash,
feePayer: tx.feePayer.toBase58(),
instructions: tx.instructions.length
});
try {
const signedTx = await this.wallet.signTransaction(tx);
console.log("transaction signed");
const txid = await this.connection.sendRawTransaction(signedTx.serialize(), {
skipPreflight: false,
preflightCommitment: "confirmed",
maxRetries: 5
});
console.log("transaction sent, signed:", txid);
const confirmation = await this.connection.confirmTransaction({
signature: txid,
blockhash: latestBlockhash.blockhash,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
}, "confirmed");
if (confirmation.value.err) {
throw new Error(`transaction confirm failed: ${JSON.stringify(confirmation.value.err)}`);
}
console.log("transaction confirmed");
const mintTokenataAccount = (0, import_spl_token2.getAssociatedTokenAddressSync)(etfAddress, this.wallet.publicKey);
const balance = await this.queries.getETFBalance(etfAddress, this.wallet.publicKey);
return {
success: true,
txid,
data: {
mintTokenataAccount,
balance,
etfAddress: params.etfAddress
}
};
} catch (error) {
console.error("purchaseETF error:", error);
throw error;
}
} catch (error) {
console.error("Error in purchaseETF:");
console.error("Error details:", error);
if (error instanceof Error) {
console.error("Error name:", error.name);
console.error("Error message:", error.message);
console.error("Error stack:", error.stack);
}
if (error instanceof anchor2.web3.SendTransactionError) {
console.error("Transaction error logs:", error.logs);
}
return {
success: false,
txid: "",
error: error instanceof Error ? error.message : "Mint ETF Token \u65F6\u53D1\u751F\u672A\u77E5\u9519\u8BEF"
};
}
}
async burnETF(params) {
try {
const etfAddress = new import_web33.PublicKey(params.etfAddress);
const etfInfo = await checkETFExists(this, etfAddress);
const tokensToCheck = [...etfInfo.assets.map((item) => item.token), etfAddress];
await checkATAExists(this, tokensToCheck, this.wallet.publicKey);
await checkBalance(this, etfAddress, this.wallet.publicKey, params.lamports);
const latestBlockhash = await this.connection.getLatestBlockhash("confirmed");
console.log("get the latest blockhash:", latestBlockhash.blockhash);
const remainingAccounts = [];
for (const item of etfInfo.assets) {
const userATA = (0, import_spl_token2.getAssociatedTokenAddressSync)(item.token, this.wallet.publicKey);
const contractATA = (0, import_spl_token2.getAssociatedTokenAddressSync)(item.token, etfInfo.etfCoreAddress, true);
remainingAccounts.push(
{ pubkey: userATA, isSigner: false, isWritable: true },
{ pubkey: contractATA, isSigner: false, isWritable: true },
{ pubkey: item.token, isSigner: false, isWritable: false }
// 添加代币Mint账户
);
}
const splTokenProgramId = new import_web33.PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
const splToken2022ProgramId = new import_web33.PublicKey("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb");
remainingAccounts.push(
{ pubkey: splTokenProgramId, isSigner: false, isWritable: false },
{ pubkey: splToken2022ProgramId, isSigner: false, isWritable: false }
);
const ix = await this.program.methods.etfBurn(params.lamports).accounts({
etfTokenMintAccount: params.etfAddress,
authority: this.wallet.publicKey,
tokenProgram: splTokenProgramId
}).remainingAccounts(remainingAccounts).transaction();
const modifyComputeUnits = anchor2.web3.ComputeBudgetProgram.setComputeUnitLimit({
units: 4e5
});
let tx = new import_web33.Transaction().add(ix).add(modifyComputeUnits);
tx.recentBlockhash = latestBlockhash.blockhash;
tx.feePayer = this.wallet.publicKey;
console.log("transaction created:", {
recentBlockhash: tx.recentBlockhash,
feePayer: tx.feePayer.toBase58(),
instructions: tx.instructions.length
});
try {
const signedTx = await this.wallet.signTransaction(tx);
console.log("transaction signed");
const txid = await this.connection.sendRawTransaction(signedTx.serialize(), {
skipPreflight: false,
preflightCommitment: "confirmed",
maxRetries: 5
});
console.log("transaction sent, signed:", txid);
const confirmation = await this.connection.confirmTransaction({
signature: txid,
blockhash: latestBlockhash.blockhash,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
}, "confirmed");
if (confirmation.value.err) {
throw new Error(`transaction confirm failed: ${JSON.stringify(confirmation.value.err)}`);
}
console.log("transaction confirmed");
const mintTokenataAccount = (0, import_spl_token2.getAssociatedTokenAddressSync)(etfAddress, this.wallet.publicKey);
const balance = await this.queries.getETFBalance(etfAddress, this.wallet.publicKey);
return {
success: true,
txid,
data: {
mintTokenataAccount,
balance,
etfAddress: params.etfAddress
}
};
} catch (error) {
console.error("burnETF error:", error);
throw error;
}
} catch (error) {
console.error("Error in burnETF:");
console.error("Error details:", error);
if (error instanceof Error) {
console.error("Error name:", error.name);
console.error("Error message:", error.message);
console.error("Error stack:", error.stack);
}
if (error instanceof anchor2.web3.SendTransactionError) {
console.error("Transaction error logs:", error.logs);
}
return {
success: false,
txid: "",
error: error instanceof Error ? error.message : "Burn ETF Token \u65F6\u53D1\u751F\u672A\u77E5\u9519\u8BEF"
};
}
}
};
//# sourceMappingURL=solana.js.map