torchsdk 1.0.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/dist/constants.d.ts +49 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +126 -0
- package/dist/constants.js.map +1 -0
- package/dist/gateway.d.ts +17 -0
- package/dist/gateway.d.ts.map +1 -0
- package/dist/gateway.js +40 -0
- package/dist/gateway.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +48 -0
- package/dist/index.js.map +1 -0
- package/dist/program.d.ts +182 -0
- package/dist/program.d.ts.map +1 -0
- package/dist/program.js +208 -0
- package/dist/program.js.map +1 -0
- package/dist/quotes.d.ts +16 -0
- package/dist/quotes.d.ts.map +1 -0
- package/dist/quotes.js +78 -0
- package/dist/quotes.js.map +1 -0
- package/dist/said.d.ts +27 -0
- package/dist/said.d.ts.map +1 -0
- package/dist/said.js +89 -0
- package/dist/said.js.map +1 -0
- package/dist/tokens.d.ts +44 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +537 -0
- package/dist/tokens.js.map +1 -0
- package/dist/torch_market.json +3172 -0
- package/dist/transactions.d.ts +93 -0
- package/dist/transactions.d.ts.map +1 -0
- package/dist/transactions.js +550 -0
- package/dist/transactions.js.map +1 -0
- package/dist/types.d.ts +194 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +34 -0
- package/readme.md +142 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transaction builders
|
|
3
|
+
*
|
|
4
|
+
* Build unsigned transactions for buy, sell, create, vote, star, and message.
|
|
5
|
+
* Agents sign these locally and submit to the network.
|
|
6
|
+
*/
|
|
7
|
+
import { Connection } from '@solana/web3.js';
|
|
8
|
+
import { BuyParams, SellParams, CreateTokenParams, VoteParams, StarParams, MessageParams, BorrowParams, RepayParams, LiquidateParams, TransactionResult, CreateTokenResult } from './types';
|
|
9
|
+
/**
|
|
10
|
+
* Build an unsigned buy transaction.
|
|
11
|
+
*
|
|
12
|
+
* @param connection - Solana RPC connection
|
|
13
|
+
* @param params - Buy parameters (mint, buyer, amount_sol in lamports, optional slippage_bps and vote)
|
|
14
|
+
* @returns Unsigned transaction and descriptive message
|
|
15
|
+
*/
|
|
16
|
+
export declare const buildBuyTransaction: (connection: Connection, params: BuyParams) => Promise<TransactionResult>;
|
|
17
|
+
/**
|
|
18
|
+
* Build an unsigned sell transaction.
|
|
19
|
+
*
|
|
20
|
+
* @param connection - Solana RPC connection
|
|
21
|
+
* @param params - Sell parameters (mint, seller, amount_tokens in raw units, optional slippage_bps)
|
|
22
|
+
* @returns Unsigned transaction and descriptive message
|
|
23
|
+
*/
|
|
24
|
+
export declare const buildSellTransaction: (connection: Connection, params: SellParams) => Promise<TransactionResult>;
|
|
25
|
+
/**
|
|
26
|
+
* Build an unsigned create token transaction.
|
|
27
|
+
*
|
|
28
|
+
* Returns the transaction (partially signed by the mint keypair) and the mint keypair
|
|
29
|
+
* so the agent can extract the mint address.
|
|
30
|
+
*
|
|
31
|
+
* @param connection - Solana RPC connection
|
|
32
|
+
* @param params - Create parameters (creator, name, symbol, metadata_uri)
|
|
33
|
+
* @returns Partially-signed transaction, mint PublicKey, and mint Keypair
|
|
34
|
+
*/
|
|
35
|
+
export declare const buildCreateTokenTransaction: (connection: Connection, params: CreateTokenParams) => Promise<CreateTokenResult>;
|
|
36
|
+
/**
|
|
37
|
+
* Build an unsigned vote transaction.
|
|
38
|
+
*
|
|
39
|
+
* @param connection - Solana RPC connection
|
|
40
|
+
* @param params - Vote parameters (mint, voter, vote: "burn" | "return")
|
|
41
|
+
* @returns Unsigned transaction and descriptive message
|
|
42
|
+
*/
|
|
43
|
+
export declare const buildVoteTransaction: (connection: Connection, params: VoteParams) => Promise<TransactionResult>;
|
|
44
|
+
/**
|
|
45
|
+
* Build an unsigned star transaction (costs 0.05 SOL).
|
|
46
|
+
*
|
|
47
|
+
* @param connection - Solana RPC connection
|
|
48
|
+
* @param params - Star parameters (mint, user)
|
|
49
|
+
* @returns Unsigned transaction and descriptive message
|
|
50
|
+
*/
|
|
51
|
+
export declare const buildStarTransaction: (connection: Connection, params: StarParams) => Promise<TransactionResult>;
|
|
52
|
+
/**
|
|
53
|
+
* Build an unsigned message transaction (SPL Memo).
|
|
54
|
+
*
|
|
55
|
+
* @param connection - Solana RPC connection
|
|
56
|
+
* @param params - Message parameters (mint, sender, message text)
|
|
57
|
+
* @returns Unsigned transaction and descriptive message
|
|
58
|
+
*/
|
|
59
|
+
export declare const buildMessageTransaction: (connection: Connection, params: MessageParams) => Promise<TransactionResult>;
|
|
60
|
+
/**
|
|
61
|
+
* Build an unsigned borrow transaction.
|
|
62
|
+
*
|
|
63
|
+
* Lock tokens as collateral in the collateral vault and receive SOL from treasury.
|
|
64
|
+
* Token must be migrated (has Raydium pool for price calculation).
|
|
65
|
+
*
|
|
66
|
+
* @param connection - Solana RPC connection
|
|
67
|
+
* @param params - Borrow parameters (mint, borrower, collateral_amount, sol_to_borrow)
|
|
68
|
+
* @returns Unsigned transaction and descriptive message
|
|
69
|
+
*/
|
|
70
|
+
export declare const buildBorrowTransaction: (connection: Connection, params: BorrowParams) => Promise<TransactionResult>;
|
|
71
|
+
/**
|
|
72
|
+
* Build an unsigned repay transaction.
|
|
73
|
+
*
|
|
74
|
+
* Repay SOL debt. Interest is paid first, then principal.
|
|
75
|
+
* Full repay returns all collateral and closes the position.
|
|
76
|
+
*
|
|
77
|
+
* @param connection - Solana RPC connection
|
|
78
|
+
* @param params - Repay parameters (mint, borrower, sol_amount)
|
|
79
|
+
* @returns Unsigned transaction and descriptive message
|
|
80
|
+
*/
|
|
81
|
+
export declare const buildRepayTransaction: (connection: Connection, params: RepayParams) => Promise<TransactionResult>;
|
|
82
|
+
/**
|
|
83
|
+
* Build an unsigned liquidate transaction.
|
|
84
|
+
*
|
|
85
|
+
* Permissionless — anyone can call when a borrower's LTV exceeds the
|
|
86
|
+
* liquidation threshold. Liquidator pays SOL and receives collateral + bonus.
|
|
87
|
+
*
|
|
88
|
+
* @param connection - Solana RPC connection
|
|
89
|
+
* @param params - Liquidate parameters (mint, liquidator, borrower)
|
|
90
|
+
* @returns Unsigned transaction and descriptive message
|
|
91
|
+
*/
|
|
92
|
+
export declare const buildLiquidateTransaction: (connection: Connection, params: LiquidateParams) => Promise<TransactionResult>;
|
|
93
|
+
//# sourceMappingURL=transactions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transactions.d.ts","sourceRoot":"","sources":["../src/transactions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,UAAU,EAOX,MAAM,iBAAiB,CAAA;AA2BxB,OAAO,EACL,SAAS,EACT,UAAU,EACV,iBAAiB,EACjB,UAAU,EACV,UAAU,EACV,aAAa,EACb,YAAY,EACZ,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,SAAS,CAAA;AA8BhB;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,GAC9B,YAAY,UAAU,EACtB,QAAQ,SAAS,KAChB,OAAO,CAAC,iBAAiB,CAgG3B,CAAA;AAMD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAC/B,YAAY,UAAU,EACtB,QAAQ,UAAU,KACjB,OAAO,CAAC,iBAAiB,CAoE3B,CAAA;AAMD;;;;;;;;;GASG;AACH,eAAO,MAAM,2BAA2B,GACtC,YAAY,UAAU,EACtB,QAAQ,iBAAiB,KACxB,OAAO,CAAC,iBAAiB,CAiE3B,CAAA;AAMD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAC/B,YAAY,UAAU,EACtB,QAAQ,UAAU,KACjB,OAAO,CAAC,iBAAiB,CA4C3B,CAAA;AAMD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAC/B,YAAY,UAAU,EACtB,QAAQ,UAAU,KACjB,OAAO,CAAC,iBAAiB,CAiD3B,CAAA;AAQD;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,GAClC,YAAY,UAAU,EACtB,QAAQ,aAAa,KACpB,OAAO,CAAC,iBAAiB,CAiC3B,CAAA;AAMD;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,GACjC,YAAY,UAAU,EACtB,QAAQ,YAAY,KACnB,OAAO,CAAC,iBAAiB,CAuD3B,CAAA;AAMD;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,GAChC,YAAY,UAAU,EACtB,QAAQ,WAAW,KAClB,OAAO,CAAC,iBAAiB,CA4C3B,CAAA;AAMD;;;;;;;;;GASG;AACH,eAAO,MAAM,yBAAyB,GACpC,YAAY,UAAU,EACtB,QAAQ,eAAe,KACtB,OAAO,CAAC,iBAAiB,CAmE3B,CAAA"}
|
|
@@ -0,0 +1,550 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Transaction builders
|
|
4
|
+
*
|
|
5
|
+
* Build unsigned transactions for buy, sell, create, vote, star, and message.
|
|
6
|
+
* Agents sign these locally and submit to the network.
|
|
7
|
+
*/
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.buildLiquidateTransaction = exports.buildRepayTransaction = exports.buildBorrowTransaction = exports.buildMessageTransaction = exports.buildStarTransaction = exports.buildVoteTransaction = exports.buildCreateTokenTransaction = exports.buildSellTransaction = exports.buildBuyTransaction = void 0;
|
|
13
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
14
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
15
|
+
const anchor_1 = require("@coral-xyz/anchor");
|
|
16
|
+
const program_1 = require("./program");
|
|
17
|
+
const constants_1 = require("./constants");
|
|
18
|
+
const tokens_1 = require("./tokens");
|
|
19
|
+
const torch_market_json_1 = __importDefault(require("./torch_market.json"));
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// Helpers
|
|
22
|
+
// ============================================================================
|
|
23
|
+
const makeDummyProvider = (connection, payer) => {
|
|
24
|
+
const dummyWallet = {
|
|
25
|
+
publicKey: payer,
|
|
26
|
+
signTransaction: async (t) => t,
|
|
27
|
+
signAllTransactions: async (t) => t,
|
|
28
|
+
};
|
|
29
|
+
return new anchor_1.AnchorProvider(connection, dummyWallet, {});
|
|
30
|
+
};
|
|
31
|
+
const finalizeTransaction = async (connection, tx, feePayer) => {
|
|
32
|
+
const { blockhash } = await connection.getLatestBlockhash();
|
|
33
|
+
tx.recentBlockhash = blockhash;
|
|
34
|
+
tx.feePayer = feePayer;
|
|
35
|
+
};
|
|
36
|
+
// ============================================================================
|
|
37
|
+
// Buy
|
|
38
|
+
// ============================================================================
|
|
39
|
+
/**
|
|
40
|
+
* Build an unsigned buy transaction.
|
|
41
|
+
*
|
|
42
|
+
* @param connection - Solana RPC connection
|
|
43
|
+
* @param params - Buy parameters (mint, buyer, amount_sol in lamports, optional slippage_bps and vote)
|
|
44
|
+
* @returns Unsigned transaction and descriptive message
|
|
45
|
+
*/
|
|
46
|
+
const buildBuyTransaction = async (connection, params) => {
|
|
47
|
+
const { mint: mintStr, buyer: buyerStr, amount_sol, slippage_bps = 100, vote } = params;
|
|
48
|
+
const mint = new web3_js_1.PublicKey(mintStr);
|
|
49
|
+
const buyer = new web3_js_1.PublicKey(buyerStr);
|
|
50
|
+
const tokenData = await (0, tokens_1.fetchTokenRaw)(connection, mint);
|
|
51
|
+
if (!tokenData)
|
|
52
|
+
throw new Error(`Token not found: ${mintStr}`);
|
|
53
|
+
const { bondingCurve } = tokenData;
|
|
54
|
+
if (bondingCurve.bonding_complete)
|
|
55
|
+
throw new Error('Bonding curve complete, trade on DEX');
|
|
56
|
+
// Calculate expected output
|
|
57
|
+
const virtualSol = BigInt(bondingCurve.virtual_sol_reserves.toString());
|
|
58
|
+
const virtualTokens = BigInt(bondingCurve.virtual_token_reserves.toString());
|
|
59
|
+
const realSol = BigInt(bondingCurve.real_sol_reserves.toString());
|
|
60
|
+
const solAmount = BigInt(amount_sol);
|
|
61
|
+
const result = (0, program_1.calculateTokensOut)(solAmount, virtualSol, virtualTokens, realSol);
|
|
62
|
+
// Apply slippage
|
|
63
|
+
const slippage = Math.max(10, Math.min(1000, slippage_bps));
|
|
64
|
+
const minTokens = (result.tokensToUser * BigInt(10000 - slippage)) / BigInt(10000);
|
|
65
|
+
// Derive PDAs
|
|
66
|
+
const [bondingCurvePda] = (0, program_1.getBondingCurvePda)(mint);
|
|
67
|
+
const [treasuryPda] = (0, program_1.getTokenTreasuryPda)(mint);
|
|
68
|
+
const [userPositionPda] = (0, program_1.getUserPositionPda)(bondingCurvePda, buyer);
|
|
69
|
+
const [userStatsPda] = (0, program_1.getUserStatsPda)(buyer);
|
|
70
|
+
const [globalConfigPda] = (0, program_1.getGlobalConfigPda)();
|
|
71
|
+
const [protocolTreasuryPda] = (0, program_1.getProtocolTreasuryPda)();
|
|
72
|
+
const bondingCurveTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(mint, bondingCurvePda, true, spl_token_1.TOKEN_2022_PROGRAM_ID);
|
|
73
|
+
const treasuryTokenAccount = (0, program_1.getTreasuryTokenAccount)(mint, treasuryPda);
|
|
74
|
+
const userTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(mint, buyer, false, spl_token_1.TOKEN_2022_PROGRAM_ID);
|
|
75
|
+
const tx = new web3_js_1.Transaction();
|
|
76
|
+
// Create user ATA if needed
|
|
77
|
+
tx.add((0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(buyer, userTokenAccount, buyer, mint, spl_token_1.TOKEN_2022_PROGRAM_ID, spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID));
|
|
78
|
+
const provider = makeDummyProvider(connection, buyer);
|
|
79
|
+
const program = new anchor_1.Program(torch_market_json_1.default, provider);
|
|
80
|
+
// Fetch global config for dev wallet
|
|
81
|
+
const globalConfigAccount = (await program.account.globalConfig.fetch(globalConfigPda));
|
|
82
|
+
const buyIx = await program.methods
|
|
83
|
+
.buy({
|
|
84
|
+
solAmount: new anchor_1.BN(amount_sol.toString()),
|
|
85
|
+
minTokensOut: new anchor_1.BN(minTokens.toString()),
|
|
86
|
+
vote: vote === 'return' ? true : vote === 'burn' ? false : null,
|
|
87
|
+
})
|
|
88
|
+
.accounts({
|
|
89
|
+
buyer,
|
|
90
|
+
globalConfig: globalConfigPda,
|
|
91
|
+
devWallet: globalConfigAccount.devWallet || globalConfigAccount.dev_wallet,
|
|
92
|
+
protocolTreasury: protocolTreasuryPda,
|
|
93
|
+
mint,
|
|
94
|
+
bondingCurve: bondingCurvePda,
|
|
95
|
+
tokenVault: bondingCurveTokenAccount,
|
|
96
|
+
treasury: treasuryPda,
|
|
97
|
+
treasuryTokenAccount,
|
|
98
|
+
userTokenAccount,
|
|
99
|
+
userPosition: userPositionPda,
|
|
100
|
+
userStats: userStatsPda,
|
|
101
|
+
tokenProgram: spl_token_1.TOKEN_2022_PROGRAM_ID,
|
|
102
|
+
associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
103
|
+
systemProgram: web3_js_1.SystemProgram.programId,
|
|
104
|
+
rent: web3_js_1.SYSVAR_RENT_PUBKEY,
|
|
105
|
+
})
|
|
106
|
+
.instruction();
|
|
107
|
+
tx.add(buyIx);
|
|
108
|
+
await finalizeTransaction(connection, tx, buyer);
|
|
109
|
+
return {
|
|
110
|
+
transaction: tx,
|
|
111
|
+
message: `Buy ${Number(result.tokensToUser) / 1e6} tokens for ${Number(solAmount) / 1e9} SOL`,
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
exports.buildBuyTransaction = buildBuyTransaction;
|
|
115
|
+
// ============================================================================
|
|
116
|
+
// Sell
|
|
117
|
+
// ============================================================================
|
|
118
|
+
/**
|
|
119
|
+
* Build an unsigned sell transaction.
|
|
120
|
+
*
|
|
121
|
+
* @param connection - Solana RPC connection
|
|
122
|
+
* @param params - Sell parameters (mint, seller, amount_tokens in raw units, optional slippage_bps)
|
|
123
|
+
* @returns Unsigned transaction and descriptive message
|
|
124
|
+
*/
|
|
125
|
+
const buildSellTransaction = async (connection, params) => {
|
|
126
|
+
const { mint: mintStr, seller: sellerStr, amount_tokens, slippage_bps = 100 } = params;
|
|
127
|
+
const mint = new web3_js_1.PublicKey(mintStr);
|
|
128
|
+
const seller = new web3_js_1.PublicKey(sellerStr);
|
|
129
|
+
const tokenData = await (0, tokens_1.fetchTokenRaw)(connection, mint);
|
|
130
|
+
if (!tokenData)
|
|
131
|
+
throw new Error(`Token not found: ${mintStr}`);
|
|
132
|
+
const { bondingCurve } = tokenData;
|
|
133
|
+
if (bondingCurve.bonding_complete)
|
|
134
|
+
throw new Error('Bonding curve complete, trade on DEX');
|
|
135
|
+
// Calculate expected output
|
|
136
|
+
const virtualSol = BigInt(bondingCurve.virtual_sol_reserves.toString());
|
|
137
|
+
const virtualTokens = BigInt(bondingCurve.virtual_token_reserves.toString());
|
|
138
|
+
const tokenAmount = BigInt(amount_tokens);
|
|
139
|
+
const result = (0, program_1.calculateSolOut)(tokenAmount, virtualSol, virtualTokens);
|
|
140
|
+
// Apply slippage
|
|
141
|
+
const slippage = Math.max(10, Math.min(1000, slippage_bps));
|
|
142
|
+
const minSol = (result.solToUser * BigInt(10000 - slippage)) / BigInt(10000);
|
|
143
|
+
// Derive PDAs
|
|
144
|
+
const [bondingCurvePda] = (0, program_1.getBondingCurvePda)(mint);
|
|
145
|
+
const [treasuryPda] = (0, program_1.getTokenTreasuryPda)(mint);
|
|
146
|
+
const [userPositionPda] = (0, program_1.getUserPositionPda)(bondingCurvePda, seller);
|
|
147
|
+
const [userStatsPda] = (0, program_1.getUserStatsPda)(seller);
|
|
148
|
+
const [globalConfigPda] = (0, program_1.getGlobalConfigPda)();
|
|
149
|
+
const bondingCurveTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(mint, bondingCurvePda, true, spl_token_1.TOKEN_2022_PROGRAM_ID);
|
|
150
|
+
const userTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(mint, seller, false, spl_token_1.TOKEN_2022_PROGRAM_ID);
|
|
151
|
+
const tx = new web3_js_1.Transaction();
|
|
152
|
+
const provider = makeDummyProvider(connection, seller);
|
|
153
|
+
const program = new anchor_1.Program(torch_market_json_1.default, provider);
|
|
154
|
+
const sellIx = await program.methods
|
|
155
|
+
.sell({
|
|
156
|
+
tokenAmount: new anchor_1.BN(amount_tokens.toString()),
|
|
157
|
+
minSolOut: new anchor_1.BN(minSol.toString()),
|
|
158
|
+
})
|
|
159
|
+
.accounts({
|
|
160
|
+
seller,
|
|
161
|
+
mint,
|
|
162
|
+
bondingCurve: bondingCurvePda,
|
|
163
|
+
tokenVault: bondingCurveTokenAccount,
|
|
164
|
+
sellerTokenAccount: userTokenAccount,
|
|
165
|
+
userPosition: userPositionPda,
|
|
166
|
+
userStats: userStatsPda,
|
|
167
|
+
tokenProgram: spl_token_1.TOKEN_2022_PROGRAM_ID,
|
|
168
|
+
systemProgram: web3_js_1.SystemProgram.programId,
|
|
169
|
+
})
|
|
170
|
+
.instruction();
|
|
171
|
+
tx.add(sellIx);
|
|
172
|
+
await finalizeTransaction(connection, tx, seller);
|
|
173
|
+
return {
|
|
174
|
+
transaction: tx,
|
|
175
|
+
message: `Sell ${Number(tokenAmount) / 1e6} tokens for ${Number(result.solToUser) / 1e9} SOL`,
|
|
176
|
+
};
|
|
177
|
+
};
|
|
178
|
+
exports.buildSellTransaction = buildSellTransaction;
|
|
179
|
+
// ============================================================================
|
|
180
|
+
// Create Token
|
|
181
|
+
// ============================================================================
|
|
182
|
+
/**
|
|
183
|
+
* Build an unsigned create token transaction.
|
|
184
|
+
*
|
|
185
|
+
* Returns the transaction (partially signed by the mint keypair) and the mint keypair
|
|
186
|
+
* so the agent can extract the mint address.
|
|
187
|
+
*
|
|
188
|
+
* @param connection - Solana RPC connection
|
|
189
|
+
* @param params - Create parameters (creator, name, symbol, metadata_uri)
|
|
190
|
+
* @returns Partially-signed transaction, mint PublicKey, and mint Keypair
|
|
191
|
+
*/
|
|
192
|
+
const buildCreateTokenTransaction = async (connection, params) => {
|
|
193
|
+
const { creator: creatorStr, name, symbol, metadata_uri } = params;
|
|
194
|
+
const creator = new web3_js_1.PublicKey(creatorStr);
|
|
195
|
+
if (name.length > 32)
|
|
196
|
+
throw new Error('Name must be 32 characters or less');
|
|
197
|
+
if (symbol.length > 10)
|
|
198
|
+
throw new Error('Symbol must be 10 characters or less');
|
|
199
|
+
// Grind for vanity "tm" suffix
|
|
200
|
+
let mint;
|
|
201
|
+
const maxAttempts = 500000;
|
|
202
|
+
let attempts = 0;
|
|
203
|
+
while (true) {
|
|
204
|
+
mint = web3_js_1.Keypair.generate();
|
|
205
|
+
attempts++;
|
|
206
|
+
if (mint.publicKey.toBase58().endsWith('tm'))
|
|
207
|
+
break;
|
|
208
|
+
if (attempts >= maxAttempts)
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
// Derive PDAs
|
|
212
|
+
const [globalConfig] = (0, program_1.getGlobalConfigPda)();
|
|
213
|
+
const [bondingCurve] = (0, program_1.getBondingCurvePda)(mint.publicKey);
|
|
214
|
+
const [treasury] = (0, program_1.getTokenTreasuryPda)(mint.publicKey);
|
|
215
|
+
const bondingCurveTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(mint.publicKey, bondingCurve, true, spl_token_1.TOKEN_2022_PROGRAM_ID);
|
|
216
|
+
const treasuryTokenAccount = (0, program_1.getTreasuryTokenAccount)(mint.publicKey, treasury);
|
|
217
|
+
const tx = new web3_js_1.Transaction();
|
|
218
|
+
const provider = makeDummyProvider(connection, creator);
|
|
219
|
+
const program = new anchor_1.Program(torch_market_json_1.default, provider);
|
|
220
|
+
const createIx = await program.methods
|
|
221
|
+
.createToken({ name, symbol, uri: metadata_uri })
|
|
222
|
+
.accounts({
|
|
223
|
+
creator,
|
|
224
|
+
globalConfig,
|
|
225
|
+
mint: mint.publicKey,
|
|
226
|
+
bondingCurve,
|
|
227
|
+
tokenVault: bondingCurveTokenAccount,
|
|
228
|
+
treasury,
|
|
229
|
+
treasuryTokenAccount,
|
|
230
|
+
token2022Program: spl_token_1.TOKEN_2022_PROGRAM_ID,
|
|
231
|
+
associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
232
|
+
systemProgram: web3_js_1.SystemProgram.programId,
|
|
233
|
+
rent: web3_js_1.SYSVAR_RENT_PUBKEY,
|
|
234
|
+
})
|
|
235
|
+
.instruction();
|
|
236
|
+
tx.add(createIx);
|
|
237
|
+
await finalizeTransaction(connection, tx, creator);
|
|
238
|
+
// Partially sign with mint keypair
|
|
239
|
+
tx.partialSign(mint);
|
|
240
|
+
return {
|
|
241
|
+
transaction: tx,
|
|
242
|
+
mint: mint.publicKey,
|
|
243
|
+
mintKeypair: mint,
|
|
244
|
+
message: `Create token "${name}" ($${symbol})`,
|
|
245
|
+
};
|
|
246
|
+
};
|
|
247
|
+
exports.buildCreateTokenTransaction = buildCreateTokenTransaction;
|
|
248
|
+
// ============================================================================
|
|
249
|
+
// Vote
|
|
250
|
+
// ============================================================================
|
|
251
|
+
/**
|
|
252
|
+
* Build an unsigned vote transaction.
|
|
253
|
+
*
|
|
254
|
+
* @param connection - Solana RPC connection
|
|
255
|
+
* @param params - Vote parameters (mint, voter, vote: "burn" | "return")
|
|
256
|
+
* @returns Unsigned transaction and descriptive message
|
|
257
|
+
*/
|
|
258
|
+
const buildVoteTransaction = async (connection, params) => {
|
|
259
|
+
const { mint: mintStr, voter: voterStr, vote } = params;
|
|
260
|
+
const mint = new web3_js_1.PublicKey(mintStr);
|
|
261
|
+
const voter = new web3_js_1.PublicKey(voterStr);
|
|
262
|
+
const tokenData = await (0, tokens_1.fetchTokenRaw)(connection, mint);
|
|
263
|
+
if (!tokenData)
|
|
264
|
+
throw new Error(`Token not found: ${mintStr}`);
|
|
265
|
+
const { bondingCurve } = tokenData;
|
|
266
|
+
if (!bondingCurve.bonding_complete)
|
|
267
|
+
throw new Error('Voting not open yet');
|
|
268
|
+
if (bondingCurve.vote_finalized)
|
|
269
|
+
throw new Error('Voting has ended');
|
|
270
|
+
// Derive PDAs
|
|
271
|
+
const [bondingCurvePda] = (0, program_1.getBondingCurvePda)(mint);
|
|
272
|
+
const [treasuryPda] = (0, program_1.getTokenTreasuryPda)(mint);
|
|
273
|
+
const [userPositionPda] = (0, program_1.getUserPositionPda)(bondingCurvePda, voter);
|
|
274
|
+
const [voteRecordPda] = (0, program_1.getVoteRecordPda)(bondingCurvePda, voter);
|
|
275
|
+
const tx = new web3_js_1.Transaction();
|
|
276
|
+
const provider = makeDummyProvider(connection, voter);
|
|
277
|
+
const program = new anchor_1.Program(torch_market_json_1.default, provider);
|
|
278
|
+
const voteIx = await program.methods
|
|
279
|
+
.vote(vote === 'return')
|
|
280
|
+
.accounts({
|
|
281
|
+
user: voter,
|
|
282
|
+
mint,
|
|
283
|
+
bondingCurve: bondingCurvePda,
|
|
284
|
+
treasury: treasuryPda,
|
|
285
|
+
userPosition: userPositionPda,
|
|
286
|
+
voteRecord: voteRecordPda,
|
|
287
|
+
systemProgram: web3_js_1.SystemProgram.programId,
|
|
288
|
+
})
|
|
289
|
+
.instruction();
|
|
290
|
+
tx.add(voteIx);
|
|
291
|
+
await finalizeTransaction(connection, tx, voter);
|
|
292
|
+
return {
|
|
293
|
+
transaction: tx,
|
|
294
|
+
message: `Vote to ${vote} treasury tokens`,
|
|
295
|
+
};
|
|
296
|
+
};
|
|
297
|
+
exports.buildVoteTransaction = buildVoteTransaction;
|
|
298
|
+
// ============================================================================
|
|
299
|
+
// Star
|
|
300
|
+
// ============================================================================
|
|
301
|
+
/**
|
|
302
|
+
* Build an unsigned star transaction (costs 0.05 SOL).
|
|
303
|
+
*
|
|
304
|
+
* @param connection - Solana RPC connection
|
|
305
|
+
* @param params - Star parameters (mint, user)
|
|
306
|
+
* @returns Unsigned transaction and descriptive message
|
|
307
|
+
*/
|
|
308
|
+
const buildStarTransaction = async (connection, params) => {
|
|
309
|
+
const { mint: mintStr, user: userStr } = params;
|
|
310
|
+
const mint = new web3_js_1.PublicKey(mintStr);
|
|
311
|
+
const user = new web3_js_1.PublicKey(userStr);
|
|
312
|
+
const tokenData = await (0, tokens_1.fetchTokenRaw)(connection, mint);
|
|
313
|
+
if (!tokenData)
|
|
314
|
+
throw new Error(`Token not found: ${mintStr}`);
|
|
315
|
+
const { bondingCurve } = tokenData;
|
|
316
|
+
if (user.equals(bondingCurve.creator)) {
|
|
317
|
+
throw new Error('Cannot star your own token');
|
|
318
|
+
}
|
|
319
|
+
// Check if already starred
|
|
320
|
+
const [starRecordPda] = (0, program_1.getStarRecordPda)(user, mint);
|
|
321
|
+
const starRecord = await connection.getAccountInfo(starRecordPda);
|
|
322
|
+
if (starRecord)
|
|
323
|
+
throw new Error('Already starred this token');
|
|
324
|
+
// Derive PDAs
|
|
325
|
+
const [bondingCurvePda] = (0, program_1.getBondingCurvePda)(mint);
|
|
326
|
+
const [treasuryPda] = (0, program_1.getTokenTreasuryPda)(mint);
|
|
327
|
+
const tx = new web3_js_1.Transaction();
|
|
328
|
+
const provider = makeDummyProvider(connection, user);
|
|
329
|
+
const program = new anchor_1.Program(torch_market_json_1.default, provider);
|
|
330
|
+
const starIx = await program.methods
|
|
331
|
+
.starToken()
|
|
332
|
+
.accounts({
|
|
333
|
+
user,
|
|
334
|
+
mint,
|
|
335
|
+
bondingCurve: bondingCurvePda,
|
|
336
|
+
treasury: treasuryPda,
|
|
337
|
+
creator: bondingCurve.creator,
|
|
338
|
+
starRecord: starRecordPda,
|
|
339
|
+
systemProgram: web3_js_1.SystemProgram.programId,
|
|
340
|
+
})
|
|
341
|
+
.instruction();
|
|
342
|
+
tx.add(starIx);
|
|
343
|
+
await finalizeTransaction(connection, tx, user);
|
|
344
|
+
return {
|
|
345
|
+
transaction: tx,
|
|
346
|
+
message: 'Star token (costs 0.05 SOL)',
|
|
347
|
+
};
|
|
348
|
+
};
|
|
349
|
+
exports.buildStarTransaction = buildStarTransaction;
|
|
350
|
+
// ============================================================================
|
|
351
|
+
// Message
|
|
352
|
+
// ============================================================================
|
|
353
|
+
const MAX_MESSAGE_LENGTH = 500;
|
|
354
|
+
/**
|
|
355
|
+
* Build an unsigned message transaction (SPL Memo).
|
|
356
|
+
*
|
|
357
|
+
* @param connection - Solana RPC connection
|
|
358
|
+
* @param params - Message parameters (mint, sender, message text)
|
|
359
|
+
* @returns Unsigned transaction and descriptive message
|
|
360
|
+
*/
|
|
361
|
+
const buildMessageTransaction = async (connection, params) => {
|
|
362
|
+
const { mint: mintStr, sender: senderStr, message } = params;
|
|
363
|
+
if (message.length > MAX_MESSAGE_LENGTH) {
|
|
364
|
+
throw new Error(`Message must be ${MAX_MESSAGE_LENGTH} characters or less`);
|
|
365
|
+
}
|
|
366
|
+
if (message.trim().length === 0) {
|
|
367
|
+
throw new Error('Message cannot be empty');
|
|
368
|
+
}
|
|
369
|
+
const mint = new web3_js_1.PublicKey(mintStr);
|
|
370
|
+
const sender = new web3_js_1.PublicKey(senderStr);
|
|
371
|
+
const tokenData = await (0, tokens_1.fetchTokenRaw)(connection, mint);
|
|
372
|
+
if (!tokenData)
|
|
373
|
+
throw new Error(`Token not found: ${mintStr}`);
|
|
374
|
+
const tx = new web3_js_1.Transaction();
|
|
375
|
+
// Prefix memo with mint address for indexing
|
|
376
|
+
const prefixedMessage = `[${mintStr}] ${message}`;
|
|
377
|
+
const memoIx = new web3_js_1.TransactionInstruction({
|
|
378
|
+
programId: constants_1.MEMO_PROGRAM_ID,
|
|
379
|
+
keys: [{ pubkey: sender, isSigner: true, isWritable: false }],
|
|
380
|
+
data: Buffer.from(prefixedMessage, 'utf-8'),
|
|
381
|
+
});
|
|
382
|
+
tx.add(memoIx);
|
|
383
|
+
await finalizeTransaction(connection, tx, sender);
|
|
384
|
+
return {
|
|
385
|
+
transaction: tx,
|
|
386
|
+
message: `Post message on token page`,
|
|
387
|
+
};
|
|
388
|
+
};
|
|
389
|
+
exports.buildMessageTransaction = buildMessageTransaction;
|
|
390
|
+
// ============================================================================
|
|
391
|
+
// Borrow (V2.4)
|
|
392
|
+
// ============================================================================
|
|
393
|
+
/**
|
|
394
|
+
* Build an unsigned borrow transaction.
|
|
395
|
+
*
|
|
396
|
+
* Lock tokens as collateral in the collateral vault and receive SOL from treasury.
|
|
397
|
+
* Token must be migrated (has Raydium pool for price calculation).
|
|
398
|
+
*
|
|
399
|
+
* @param connection - Solana RPC connection
|
|
400
|
+
* @param params - Borrow parameters (mint, borrower, collateral_amount, sol_to_borrow)
|
|
401
|
+
* @returns Unsigned transaction and descriptive message
|
|
402
|
+
*/
|
|
403
|
+
const buildBorrowTransaction = async (connection, params) => {
|
|
404
|
+
const { mint: mintStr, borrower: borrowerStr, collateral_amount, sol_to_borrow } = params;
|
|
405
|
+
const mint = new web3_js_1.PublicKey(mintStr);
|
|
406
|
+
const borrower = new web3_js_1.PublicKey(borrowerStr);
|
|
407
|
+
// Derive PDAs
|
|
408
|
+
const [bondingCurvePda] = (0, program_1.getBondingCurvePda)(mint);
|
|
409
|
+
const [treasuryPda] = (0, program_1.getTokenTreasuryPda)(mint);
|
|
410
|
+
const [collateralVaultPda] = (0, program_1.getCollateralVaultPda)(mint);
|
|
411
|
+
const [loanPositionPda] = (0, program_1.getLoanPositionPda)(mint, borrower);
|
|
412
|
+
const borrowerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(mint, borrower, false, spl_token_1.TOKEN_2022_PROGRAM_ID);
|
|
413
|
+
// Get Raydium pool accounts for price calculation
|
|
414
|
+
const raydium = (0, program_1.getRaydiumMigrationAccounts)(mint);
|
|
415
|
+
const tx = new web3_js_1.Transaction();
|
|
416
|
+
const provider = makeDummyProvider(connection, borrower);
|
|
417
|
+
const program = new anchor_1.Program(torch_market_json_1.default, provider);
|
|
418
|
+
const borrowIx = await program.methods
|
|
419
|
+
.borrow({
|
|
420
|
+
collateralAmount: new anchor_1.BN(collateral_amount.toString()),
|
|
421
|
+
solToBorrow: new anchor_1.BN(sol_to_borrow.toString()),
|
|
422
|
+
})
|
|
423
|
+
.accounts({
|
|
424
|
+
borrower,
|
|
425
|
+
mint,
|
|
426
|
+
bondingCurve: bondingCurvePda,
|
|
427
|
+
treasury: treasuryPda,
|
|
428
|
+
collateralVault: collateralVaultPda,
|
|
429
|
+
borrowerTokenAccount,
|
|
430
|
+
loanPosition: loanPositionPda,
|
|
431
|
+
poolState: raydium.poolState,
|
|
432
|
+
tokenVault0: raydium.token0Vault,
|
|
433
|
+
tokenVault1: raydium.token1Vault,
|
|
434
|
+
tokenProgram: spl_token_1.TOKEN_2022_PROGRAM_ID,
|
|
435
|
+
systemProgram: web3_js_1.SystemProgram.programId,
|
|
436
|
+
})
|
|
437
|
+
.instruction();
|
|
438
|
+
tx.add(borrowIx);
|
|
439
|
+
await finalizeTransaction(connection, tx, borrower);
|
|
440
|
+
return {
|
|
441
|
+
transaction: tx,
|
|
442
|
+
message: `Borrow ${Number(sol_to_borrow) / 1e9} SOL with ${Number(collateral_amount) / 1e6} tokens as collateral`,
|
|
443
|
+
};
|
|
444
|
+
};
|
|
445
|
+
exports.buildBorrowTransaction = buildBorrowTransaction;
|
|
446
|
+
// ============================================================================
|
|
447
|
+
// Repay (V2.4)
|
|
448
|
+
// ============================================================================
|
|
449
|
+
/**
|
|
450
|
+
* Build an unsigned repay transaction.
|
|
451
|
+
*
|
|
452
|
+
* Repay SOL debt. Interest is paid first, then principal.
|
|
453
|
+
* Full repay returns all collateral and closes the position.
|
|
454
|
+
*
|
|
455
|
+
* @param connection - Solana RPC connection
|
|
456
|
+
* @param params - Repay parameters (mint, borrower, sol_amount)
|
|
457
|
+
* @returns Unsigned transaction and descriptive message
|
|
458
|
+
*/
|
|
459
|
+
const buildRepayTransaction = async (connection, params) => {
|
|
460
|
+
const { mint: mintStr, borrower: borrowerStr, sol_amount } = params;
|
|
461
|
+
const mint = new web3_js_1.PublicKey(mintStr);
|
|
462
|
+
const borrower = new web3_js_1.PublicKey(borrowerStr);
|
|
463
|
+
// Derive PDAs
|
|
464
|
+
const [treasuryPda] = (0, program_1.getTokenTreasuryPda)(mint);
|
|
465
|
+
const [collateralVaultPda] = (0, program_1.getCollateralVaultPda)(mint);
|
|
466
|
+
const [loanPositionPda] = (0, program_1.getLoanPositionPda)(mint, borrower);
|
|
467
|
+
const borrowerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(mint, borrower, false, spl_token_1.TOKEN_2022_PROGRAM_ID);
|
|
468
|
+
const tx = new web3_js_1.Transaction();
|
|
469
|
+
const provider = makeDummyProvider(connection, borrower);
|
|
470
|
+
const program = new anchor_1.Program(torch_market_json_1.default, provider);
|
|
471
|
+
const repayIx = await program.methods
|
|
472
|
+
.repay(new anchor_1.BN(sol_amount.toString()))
|
|
473
|
+
.accounts({
|
|
474
|
+
borrower,
|
|
475
|
+
mint,
|
|
476
|
+
treasury: treasuryPda,
|
|
477
|
+
collateralVault: collateralVaultPda,
|
|
478
|
+
borrowerTokenAccount,
|
|
479
|
+
loanPosition: loanPositionPda,
|
|
480
|
+
tokenProgram: spl_token_1.TOKEN_2022_PROGRAM_ID,
|
|
481
|
+
systemProgram: web3_js_1.SystemProgram.programId,
|
|
482
|
+
})
|
|
483
|
+
.instruction();
|
|
484
|
+
tx.add(repayIx);
|
|
485
|
+
await finalizeTransaction(connection, tx, borrower);
|
|
486
|
+
return {
|
|
487
|
+
transaction: tx,
|
|
488
|
+
message: `Repay ${Number(sol_amount) / 1e9} SOL`,
|
|
489
|
+
};
|
|
490
|
+
};
|
|
491
|
+
exports.buildRepayTransaction = buildRepayTransaction;
|
|
492
|
+
// ============================================================================
|
|
493
|
+
// Liquidate (V2.4)
|
|
494
|
+
// ============================================================================
|
|
495
|
+
/**
|
|
496
|
+
* Build an unsigned liquidate transaction.
|
|
497
|
+
*
|
|
498
|
+
* Permissionless — anyone can call when a borrower's LTV exceeds the
|
|
499
|
+
* liquidation threshold. Liquidator pays SOL and receives collateral + bonus.
|
|
500
|
+
*
|
|
501
|
+
* @param connection - Solana RPC connection
|
|
502
|
+
* @param params - Liquidate parameters (mint, liquidator, borrower)
|
|
503
|
+
* @returns Unsigned transaction and descriptive message
|
|
504
|
+
*/
|
|
505
|
+
const buildLiquidateTransaction = async (connection, params) => {
|
|
506
|
+
const { mint: mintStr, liquidator: liquidatorStr, borrower: borrowerStr } = params;
|
|
507
|
+
const mint = new web3_js_1.PublicKey(mintStr);
|
|
508
|
+
const liquidator = new web3_js_1.PublicKey(liquidatorStr);
|
|
509
|
+
const borrower = new web3_js_1.PublicKey(borrowerStr);
|
|
510
|
+
// Derive PDAs
|
|
511
|
+
const [bondingCurvePda] = (0, program_1.getBondingCurvePda)(mint);
|
|
512
|
+
const [treasuryPda] = (0, program_1.getTokenTreasuryPda)(mint);
|
|
513
|
+
const [collateralVaultPda] = (0, program_1.getCollateralVaultPda)(mint);
|
|
514
|
+
const [loanPositionPda] = (0, program_1.getLoanPositionPda)(mint, borrower);
|
|
515
|
+
const liquidatorTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(mint, liquidator, false, spl_token_1.TOKEN_2022_PROGRAM_ID);
|
|
516
|
+
// Get Raydium pool accounts for price calculation
|
|
517
|
+
const raydium = (0, program_1.getRaydiumMigrationAccounts)(mint);
|
|
518
|
+
const tx = new web3_js_1.Transaction();
|
|
519
|
+
// Create liquidator ATA if needed
|
|
520
|
+
tx.add((0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(liquidator, liquidatorTokenAccount, liquidator, mint, spl_token_1.TOKEN_2022_PROGRAM_ID, spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID));
|
|
521
|
+
const provider = makeDummyProvider(connection, liquidator);
|
|
522
|
+
const program = new anchor_1.Program(torch_market_json_1.default, provider);
|
|
523
|
+
const liquidateIx = await program.methods
|
|
524
|
+
.liquidate()
|
|
525
|
+
.accounts({
|
|
526
|
+
liquidator,
|
|
527
|
+
borrower,
|
|
528
|
+
mint,
|
|
529
|
+
bondingCurve: bondingCurvePda,
|
|
530
|
+
treasury: treasuryPda,
|
|
531
|
+
collateralVault: collateralVaultPda,
|
|
532
|
+
liquidatorTokenAccount,
|
|
533
|
+
loanPosition: loanPositionPda,
|
|
534
|
+
poolState: raydium.poolState,
|
|
535
|
+
tokenVault0: raydium.token0Vault,
|
|
536
|
+
tokenVault1: raydium.token1Vault,
|
|
537
|
+
tokenProgram: spl_token_1.TOKEN_2022_PROGRAM_ID,
|
|
538
|
+
associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
539
|
+
systemProgram: web3_js_1.SystemProgram.programId,
|
|
540
|
+
})
|
|
541
|
+
.instruction();
|
|
542
|
+
tx.add(liquidateIx);
|
|
543
|
+
await finalizeTransaction(connection, tx, liquidator);
|
|
544
|
+
return {
|
|
545
|
+
transaction: tx,
|
|
546
|
+
message: `Liquidate loan position for ${borrowerStr}`,
|
|
547
|
+
};
|
|
548
|
+
};
|
|
549
|
+
exports.buildLiquidateTransaction = buildLiquidateTransaction;
|
|
550
|
+
//# sourceMappingURL=transactions.js.map
|