@ghostspeak/sdk 2.0.6 → 2.0.8
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/README.md +295 -30
- package/dist/GhostSpeakClient-bnXwUPHI.d.ts +1011 -0
- package/dist/StakingModule-DunDShLq.d.ts +2446 -0
- package/dist/{agent-M74TCRON.js → agent-S42FIMR7.js} +4 -4
- package/dist/{agent-M74TCRON.js.map → agent-S42FIMR7.js.map} +1 -1
- package/dist/batch-operations-45CQFEID.js +4 -0
- package/dist/batch-operations-45CQFEID.js.map +1 -0
- package/dist/browser-CI5_6Gzk.d.ts +234 -0
- package/dist/browser.d.ts +6 -576
- package/dist/browser.js +15 -842
- package/dist/browser.js.map +1 -1
- package/dist/chunk-46QWY3MG.js +156 -0
- package/dist/chunk-46QWY3MG.js.map +1 -0
- package/dist/{chunk-F3DZMBUA.js → chunk-5QBSC4T4.js} +327 -493
- package/dist/chunk-5QBSC4T4.js.map +1 -0
- package/dist/chunk-5QZVFUXB.js +4176 -0
- package/dist/chunk-5QZVFUXB.js.map +1 -0
- package/dist/chunk-6XCCMJ6M.js +1865 -0
- package/dist/chunk-6XCCMJ6M.js.map +1 -0
- package/dist/chunk-A7ALCVUI.js +98 -0
- package/dist/chunk-A7ALCVUI.js.map +1 -0
- package/dist/chunk-AWMGX3OX.js +814 -0
- package/dist/chunk-AWMGX3OX.js.map +1 -0
- package/dist/chunk-BF3IQ35I.js +284 -0
- package/dist/chunk-BF3IQ35I.js.map +1 -0
- package/dist/chunk-BQDGRTVP.js +168 -0
- package/dist/chunk-BQDGRTVP.js.map +1 -0
- package/dist/chunk-IQM5RASO.js +8502 -0
- package/dist/chunk-IQM5RASO.js.map +1 -0
- package/dist/chunk-JYXSOXCP.js +3850 -0
- package/dist/chunk-JYXSOXCP.js.map +1 -0
- package/dist/chunk-OXA7MECJ.js +7787 -0
- package/dist/chunk-OXA7MECJ.js.map +1 -0
- package/dist/chunk-QLRWUHN2.js +231 -0
- package/dist/chunk-QLRWUHN2.js.map +1 -0
- package/dist/chunk-SKMJJ3Q6.js +125 -0
- package/dist/chunk-SKMJJ3Q6.js.map +1 -0
- package/dist/chunk-TTB4OS2D.js +69 -0
- package/dist/chunk-TTB4OS2D.js.map +1 -0
- package/dist/chunk-UP2VWCW5.js +33 -0
- package/dist/{chunk-NSBPE2FW.js.map → chunk-UP2VWCW5.js.map} +1 -1
- package/dist/{chunk-UJUGGLMT.js → chunk-VQZQCHUT.js} +5 -5
- package/dist/{chunk-UJUGGLMT.js.map → chunk-VQZQCHUT.js.map} +1 -1
- package/dist/client.d.ts +4 -4
- package/dist/client.js +11 -10
- package/dist/createAgentAuthorization-KGZNXZBT.js +5 -0
- package/dist/createAgentAuthorization-KGZNXZBT.js.map +1 -0
- package/dist/credentials.js +1 -1
- package/dist/crypto.js +2 -2
- package/dist/errors.js +1 -1
- package/dist/feature-flags-B1g0DCPe.d.ts +1181 -0
- package/dist/generated-QJREJQ2C.js +9 -0
- package/dist/{generated-VNLHMR6Y.js.map → generated-QJREJQ2C.js.map} +1 -1
- package/dist/{ghostspeak_wasm-SB2RPJ3D.js → ghostspeak_wasm-F227HOSM.js} +3 -3
- package/dist/{ghostspeak_wasm-SB2RPJ3D.js.map → ghostspeak_wasm-F227HOSM.js.map} +1 -1
- package/dist/index.d.ts +1179 -1498
- package/dist/index.js +356 -3578
- package/dist/index.js.map +1 -1
- package/dist/metafile-esm.json +1 -1
- package/dist/minimal/core-minimal.d.ts +2446 -1245
- package/dist/minimal/core-minimal.js +9 -9
- package/dist/minimal/core-minimal.js.map +1 -1
- package/dist/nacl-fast-W5BJ3KZ2.js +2229 -0
- package/dist/nacl-fast-W5BJ3KZ2.js.map +1 -0
- package/dist/pda-4KP7CURF.js +4 -0
- package/dist/pda-4KP7CURF.js.map +1 -0
- package/dist/pda-Ce7VYg4T.d.ts +25 -0
- package/dist/reputation-types-Yebf0Rm_.d.ts +1071 -0
- package/dist/revokeAuthorization-2ZRO6GUZ.js +5 -0
- package/dist/revokeAuthorization-2ZRO6GUZ.js.map +1 -0
- package/dist/signature-verification-DGxR4aYQ.d.ts +448 -0
- package/dist/types.js +1 -1
- package/dist/updateReputationWithAuth-PCEUOCFV.js +5 -0
- package/dist/updateReputationWithAuth-PCEUOCFV.js.map +1 -0
- package/dist/utils.d.ts +69 -203
- package/dist/utils.js +15 -153
- package/dist/utils.js.map +1 -1
- package/package.json +27 -34
- package/dist/.tsbuildinfo +0 -1
- package/dist/GhostSpeakClient-D_66Uzsf.d.ts +0 -707
- package/dist/GovernanceModule-DQYYys-H.d.ts +0 -1766
- package/dist/chunk-APCKGD23.js +0 -1328
- package/dist/chunk-APCKGD23.js.map +0 -1
- package/dist/chunk-ASQXX4IT.js +0 -572
- package/dist/chunk-ASQXX4IT.js.map +0 -1
- package/dist/chunk-COGZFWOT.js +0 -19657
- package/dist/chunk-COGZFWOT.js.map +0 -1
- package/dist/chunk-F3DZMBUA.js.map +0 -1
- package/dist/chunk-GMHIUK2R.js +0 -7526
- package/dist/chunk-GMHIUK2R.js.map +0 -1
- package/dist/chunk-IAWBZYPE.js +0 -356
- package/dist/chunk-IAWBZYPE.js.map +0 -1
- package/dist/chunk-NSBPE2FW.js +0 -15
- package/dist/chunk-OWYHJG6H.js +0 -13311
- package/dist/chunk-OWYHJG6H.js.map +0 -1
- package/dist/chunk-RDDPOFR5.js +0 -3
- package/dist/chunk-RDDPOFR5.js.map +0 -1
- package/dist/chunk-RERCHKZP.js +0 -35
- package/dist/chunk-RERCHKZP.js.map +0 -1
- package/dist/chunk-TVVGXYCI.js +0 -2887
- package/dist/chunk-TVVGXYCI.js.map +0 -1
- package/dist/chunk-ZGP5552B.js +0 -377
- package/dist/chunk-ZGP5552B.js.map +0 -1
- package/dist/chunk-ZWOYNHVK.js +0 -196
- package/dist/chunk-ZWOYNHVK.js.map +0 -1
- package/dist/dist/.tsbuildinfo +0 -1
- package/dist/elgamal-VZLWB3XK.js +0 -5
- package/dist/elgamal-VZLWB3XK.js.map +0 -1
- package/dist/feature-flags-V722ZuXO.d.ts +0 -3512
- package/dist/generated-VNLHMR6Y.js +0 -5
- package/dist/ipfs-types-BOt9ZNg4.d.ts +0 -592
- package/dist/multisigConfig-BzEhy6jy.d.ts +0 -58
- package/dist/pda-B_nS8SbD.d.ts +0 -114
- package/dist/pda-S4BFJVGE.js +0 -4
- package/dist/pda-S4BFJVGE.js.map +0 -1
- package/dist/system-addresses-BFNLEbFx.d.ts +0 -857
- package/dist/token-2022-rpc-RALH4RK7.js +0 -593
- package/dist/token-2022-rpc-RALH4RK7.js.map +0 -1
package/dist/chunk-TVVGXYCI.js
DELETED
|
@@ -1,2887 +0,0 @@
|
|
|
1
|
-
import { createErrorContext, logEnhancedError, IPFSClient, SYSTEM_PROGRAM_ADDRESS, TOKEN_2022_PROGRAM_ADDRESS, NATIVE_MINT_ADDRESS, ASSOCIATED_TOKEN_PROGRAM_ADDRESS } from './chunk-OWYHJG6H.js';
|
|
2
|
-
import { getCreateEscrowInstructionAsync, getCreateEscrowWithSolInstructionAsync, getCompleteEscrowInstruction, getCancelEscrowInstruction, getDisputeEscrowInstruction, getProcessPartialRefundInstruction, getCreateEnhancedChannelInstructionAsync, getSendEnhancedMessageInstructionAsync, getJoinChannelInstruction, getLeaveChannelInstruction, getUpdateChannelSettingsInstruction, getAddMessageReactionInstruction, getCreateServiceListingInstructionAsync, getPurchaseServiceInstruction, getCreateJobPostingInstructionAsync, getApplyToJobInstructionAsync, getAcceptJobApplicationInstructionAsync, getCreateServiceAuctionInstructionAsync, getPlaceAuctionBidInstruction, getFinalizeAuctionInstruction, getUpdateAgentServiceInstruction, getInitializeGovernanceProposalInstructionAsync, getCastVoteInstruction, getDelegateVoteInstruction, getExecuteProposalInstruction, getTallyVotesInstruction, getCreateToken2022MintInstructionAsync, getInitializeConfidentialTransferMintInstructionAsync, getInitializeInterestBearingConfigInstructionAsync, getInitializeMintCloseAuthorityInstructionAsync, getInitializeDefaultAccountStateInstructionAsync, getApproveExtensionInstruction, getRegisterAgentInstructionAsync, getRegisterAgentCompressedInstructionAsync, getUpdateAgentInstruction, getVerifyAgentInstructionAsync, getDeactivateAgentInstruction, getActivateAgentInstruction } from './chunk-COGZFWOT.js';
|
|
3
|
-
import { deriveChannelPda, deriveMessagePda, deriveJobPostingPda, deriveAuctionPda } from './chunk-ASQXX4IT.js';
|
|
4
|
-
import { createSolanaRpc, createSolanaRpcSubscriptions, lamports, pipe, createTransactionMessage, setTransactionMessageFeePayerSigner, setTransactionMessageLifetimeUsingBlockhash, appendTransactionMessageInstructions, signTransactionMessageWithSigners, setTransactionMessageFeePayer, compileTransactionMessage, getBase64EncodedWireTransaction, getProgramDerivedAddress, getAddressEncoder } from '@solana/kit';
|
|
5
|
-
import { address } from '@solana/addresses';
|
|
6
|
-
import { generateKeyPairSigner } from '@solana/signers';
|
|
7
|
-
|
|
8
|
-
var RpcClient = class {
|
|
9
|
-
rpc;
|
|
10
|
-
rpcSubscriptions;
|
|
11
|
-
commitment;
|
|
12
|
-
endpoint;
|
|
13
|
-
maxRetries;
|
|
14
|
-
retryDelay;
|
|
15
|
-
timeout;
|
|
16
|
-
constructor(config) {
|
|
17
|
-
this.endpoint = config.endpoint;
|
|
18
|
-
this.rpc = createSolanaRpc(config.endpoint);
|
|
19
|
-
this.commitment = config.commitment ?? "confirmed";
|
|
20
|
-
this.maxRetries = config.maxRetries ?? 3;
|
|
21
|
-
this.retryDelay = config.retryDelay ?? 1e3;
|
|
22
|
-
this.timeout = config.timeout ?? 6e4;
|
|
23
|
-
if (config.wsEndpoint) {
|
|
24
|
-
this.rpcSubscriptions = createSolanaRpcSubscriptions(config.wsEndpoint);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Get account information with automatic retries
|
|
29
|
-
*/
|
|
30
|
-
async getAccountInfo(address2, options) {
|
|
31
|
-
return this.withRetry(async () => {
|
|
32
|
-
const result = await this.rpc.getAccountInfo(address2, {
|
|
33
|
-
commitment: options?.commitment ?? this.commitment,
|
|
34
|
-
encoding: "base64"
|
|
35
|
-
}).send();
|
|
36
|
-
if (!result.value) return null;
|
|
37
|
-
return this.parseAccountInfo(result.value);
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Get multiple accounts efficiently
|
|
42
|
-
*/
|
|
43
|
-
async getMultipleAccounts(addresses, options) {
|
|
44
|
-
return this.withRetry(async () => {
|
|
45
|
-
const result = await this.rpc.getMultipleAccounts(addresses, {
|
|
46
|
-
commitment: options?.commitment ?? this.commitment,
|
|
47
|
-
encoding: "base64"
|
|
48
|
-
}).send();
|
|
49
|
-
return result.value.map(
|
|
50
|
-
(account) => account ? this.parseAccountInfo(account) : null
|
|
51
|
-
);
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Get program accounts with filters
|
|
56
|
-
*/
|
|
57
|
-
async getProgramAccounts(programId, options) {
|
|
58
|
-
return this.withRetry(async () => {
|
|
59
|
-
const result = await this.rpc.getProgramAccounts(programId, {
|
|
60
|
-
commitment: options?.commitment ?? this.commitment,
|
|
61
|
-
encoding: "base64",
|
|
62
|
-
filters: options?.filters
|
|
63
|
-
}).send();
|
|
64
|
-
return result.map((item) => {
|
|
65
|
-
const typedItem = item;
|
|
66
|
-
return {
|
|
67
|
-
pubkey: typedItem.pubkey,
|
|
68
|
-
account: this.parseAccountInfo(typedItem.account)
|
|
69
|
-
};
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Get latest blockhash with automatic caching
|
|
75
|
-
*/
|
|
76
|
-
blockhashCache = null;
|
|
77
|
-
async getLatestBlockhash() {
|
|
78
|
-
const now = Date.now();
|
|
79
|
-
if (this.blockhashCache && now - this.blockhashCache.timestamp < 1e3) {
|
|
80
|
-
return this.blockhashCache.value;
|
|
81
|
-
}
|
|
82
|
-
const result = await this.withRetry(async () => {
|
|
83
|
-
const response = await this.rpc.getLatestBlockhash({
|
|
84
|
-
commitment: this.commitment
|
|
85
|
-
}).send();
|
|
86
|
-
return {
|
|
87
|
-
blockhash: response.value.blockhash,
|
|
88
|
-
lastValidBlockHeight: BigInt(response.value.lastValidBlockHeight)
|
|
89
|
-
};
|
|
90
|
-
});
|
|
91
|
-
this.blockhashCache = { value: result, timestamp: now };
|
|
92
|
-
return result;
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Send transaction with enhanced error handling
|
|
96
|
-
*/
|
|
97
|
-
async sendTransaction(transaction, options) {
|
|
98
|
-
return this.withRetry(async () => {
|
|
99
|
-
const result = await this.rpc.sendTransaction(transaction, {
|
|
100
|
-
encoding: "base64",
|
|
101
|
-
skipPreflight: options?.skipPreflight ?? false,
|
|
102
|
-
preflightCommitment: options?.preflightCommitment ?? this.commitment,
|
|
103
|
-
maxRetries: options?.maxRetries ? BigInt(options.maxRetries) : void 0
|
|
104
|
-
}).send();
|
|
105
|
-
return result;
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Get signature statuses with batch support
|
|
110
|
-
*/
|
|
111
|
-
async getSignatureStatuses(signatures) {
|
|
112
|
-
return this.withRetry(async () => {
|
|
113
|
-
const result = await this.rpc.getSignatureStatuses(signatures).send();
|
|
114
|
-
return result.value.map((status) => {
|
|
115
|
-
if (!status) return null;
|
|
116
|
-
const typedStatus = status;
|
|
117
|
-
return {
|
|
118
|
-
slot: typedStatus.slot,
|
|
119
|
-
confirmations: typedStatus.confirmations,
|
|
120
|
-
err: typedStatus.err,
|
|
121
|
-
confirmationStatus: typedStatus.confirmationStatus
|
|
122
|
-
};
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Simulate transaction with detailed error info
|
|
128
|
-
*/
|
|
129
|
-
async simulateTransaction(transaction, options) {
|
|
130
|
-
return this.withRetry(async () => {
|
|
131
|
-
const result = await this.rpc.simulateTransaction(transaction, {
|
|
132
|
-
encoding: "base64",
|
|
133
|
-
commitment: options?.commitment ?? this.commitment,
|
|
134
|
-
replaceRecentBlockhash: options?.replaceRecentBlockhash ?? false
|
|
135
|
-
}).send();
|
|
136
|
-
return {
|
|
137
|
-
err: result.value.err,
|
|
138
|
-
logs: result.value.logs ?? [],
|
|
139
|
-
unitsConsumed: result.value.unitsConsumed ? BigInt(result.value.unitsConsumed) : void 0,
|
|
140
|
-
returnData: result.value.returnData
|
|
141
|
-
};
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Get fee for message
|
|
146
|
-
*/
|
|
147
|
-
async getFeeForMessage(encodedMessage) {
|
|
148
|
-
return this.withRetry(async () => {
|
|
149
|
-
const result = await this.rpc.getFeeForMessage(encodedMessage, {
|
|
150
|
-
commitment: this.commitment
|
|
151
|
-
}).send();
|
|
152
|
-
return result.value ? BigInt(result.value) : null;
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* Health check
|
|
157
|
-
*/
|
|
158
|
-
async isHealthy() {
|
|
159
|
-
try {
|
|
160
|
-
await this.rpc.getHealth().send();
|
|
161
|
-
return true;
|
|
162
|
-
} catch {
|
|
163
|
-
return false;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* Get RPC node version
|
|
168
|
-
*/
|
|
169
|
-
async getVersion() {
|
|
170
|
-
const result = await this.rpc.getVersion().send();
|
|
171
|
-
return result;
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Subscribe to account changes (WebSocket)
|
|
175
|
-
* Note: This is a placeholder implementation. In production, you would use the actual subscription API
|
|
176
|
-
*/
|
|
177
|
-
async subscribeToAccount(address2, callback) {
|
|
178
|
-
if (!this.rpcSubscriptions) {
|
|
179
|
-
throw new Error("WebSocket endpoint not configured");
|
|
180
|
-
}
|
|
181
|
-
console.warn("Account subscription is not fully implemented in this version");
|
|
182
|
-
const intervalId = setInterval(async () => {
|
|
183
|
-
try {
|
|
184
|
-
const accountInfo = await this.getAccountInfo(address2);
|
|
185
|
-
callback(accountInfo);
|
|
186
|
-
} catch (error) {
|
|
187
|
-
console.error("Subscription polling error:", error);
|
|
188
|
-
}
|
|
189
|
-
}, 5e3);
|
|
190
|
-
return () => {
|
|
191
|
-
clearInterval(intervalId);
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
// Private helper methods
|
|
195
|
-
async withRetry(operation, retries = this.maxRetries) {
|
|
196
|
-
let lastError;
|
|
197
|
-
for (let i = 0; i <= retries; i++) {
|
|
198
|
-
try {
|
|
199
|
-
return await operation();
|
|
200
|
-
} catch (error) {
|
|
201
|
-
lastError = error;
|
|
202
|
-
if (i < retries) {
|
|
203
|
-
await new Promise((resolve) => setTimeout(resolve, this.retryDelay * Math.pow(2, i)));
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
throw lastError;
|
|
208
|
-
}
|
|
209
|
-
parseAccountInfo(rawAccount) {
|
|
210
|
-
const account = rawAccount;
|
|
211
|
-
const dataArray = account.data;
|
|
212
|
-
const base64Data = Array.isArray(dataArray) ? dataArray[0] : dataArray;
|
|
213
|
-
return {
|
|
214
|
-
executable: account.executable,
|
|
215
|
-
lamports: typeof account.lamports === "number" ? lamports(BigInt(account.lamports)) : account.lamports,
|
|
216
|
-
owner: account.owner,
|
|
217
|
-
rentEpoch: account.rentEpoch !== void 0 ? typeof account.rentEpoch === "number" ? BigInt(account.rentEpoch) : account.rentEpoch : BigInt(0),
|
|
218
|
-
data: Buffer.from(base64Data, "base64"),
|
|
219
|
-
space: account.space ? typeof account.space === "number" ? BigInt(account.space) : account.space : void 0
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
};
|
|
223
|
-
|
|
224
|
-
// src/utils/transaction-urls.ts
|
|
225
|
-
function getSolanaExplorerUrl(signature, cluster = "mainnet-beta") {
|
|
226
|
-
const baseUrl = "https://explorer.solana.com/tx";
|
|
227
|
-
switch (cluster) {
|
|
228
|
-
case "devnet":
|
|
229
|
-
return `${baseUrl}/${signature}?cluster=devnet`;
|
|
230
|
-
case "testnet":
|
|
231
|
-
return `${baseUrl}/${signature}?cluster=testnet`;
|
|
232
|
-
case "localnet":
|
|
233
|
-
return `${baseUrl}/${signature}?cluster=custom&customUrl=http://localhost:8899`;
|
|
234
|
-
default:
|
|
235
|
-
return `${baseUrl}/${signature}`;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
function getSolscanUrl(signature, cluster = "mainnet-beta") {
|
|
239
|
-
const baseUrl = "https://solscan.io/tx";
|
|
240
|
-
switch (cluster) {
|
|
241
|
-
case "devnet":
|
|
242
|
-
return `${baseUrl}/${signature}?cluster=devnet`;
|
|
243
|
-
case "testnet":
|
|
244
|
-
return `${baseUrl}/${signature}?cluster=testnet`;
|
|
245
|
-
case "localnet":
|
|
246
|
-
return `Local transaction: ${signature} (not viewable on Solscan)`;
|
|
247
|
-
default:
|
|
248
|
-
return `${baseUrl}/${signature}`;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
function getSolanaFMUrl(signature, cluster = "mainnet-beta") {
|
|
252
|
-
const baseUrl = "https://solana.fm/tx";
|
|
253
|
-
switch (cluster) {
|
|
254
|
-
case "devnet":
|
|
255
|
-
return `${baseUrl}/${signature}?cluster=devnet-solana`;
|
|
256
|
-
case "testnet":
|
|
257
|
-
return `${baseUrl}/${signature}?cluster=testnet-solana`;
|
|
258
|
-
case "localnet":
|
|
259
|
-
return `Local transaction: ${signature} (not viewable on SolanaFM)`;
|
|
260
|
-
default:
|
|
261
|
-
return `${baseUrl}/${signature}`;
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
function getXrayUrl(signature, cluster = "mainnet-beta") {
|
|
265
|
-
const baseUrl = "https://xray.helius.xyz/tx";
|
|
266
|
-
switch (cluster) {
|
|
267
|
-
case "devnet":
|
|
268
|
-
return `${baseUrl}/${signature}?network=devnet`;
|
|
269
|
-
case "testnet":
|
|
270
|
-
return `${baseUrl}/${signature}?network=testnet`;
|
|
271
|
-
case "localnet":
|
|
272
|
-
return `Local transaction: ${signature} (not viewable on XRAY)`;
|
|
273
|
-
default:
|
|
274
|
-
return `${baseUrl}/${signature}`;
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
function generateExplorerUrls(signature, cluster = "mainnet-beta") {
|
|
278
|
-
return {
|
|
279
|
-
solanaExplorer: getSolanaExplorerUrl(signature, cluster),
|
|
280
|
-
solscan: getSolscanUrl(signature, cluster),
|
|
281
|
-
solanaFM: getSolanaFMUrl(signature, cluster),
|
|
282
|
-
xray: getXrayUrl(signature, cluster)
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
function createTransactionResult(signature, cluster, commitment = "confirmed") {
|
|
286
|
-
return {
|
|
287
|
-
signature,
|
|
288
|
-
cluster,
|
|
289
|
-
urls: generateExplorerUrls(signature, cluster),
|
|
290
|
-
commitment,
|
|
291
|
-
timestamp: Date.now()
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// src/core/DevTools.ts
|
|
296
|
-
var DevTools = class _DevTools {
|
|
297
|
-
static instance = null;
|
|
298
|
-
rpcClient;
|
|
299
|
-
config;
|
|
300
|
-
isDevelopment;
|
|
301
|
-
logs = [];
|
|
302
|
-
timings = /* @__PURE__ */ new Map();
|
|
303
|
-
constructor(config) {
|
|
304
|
-
this.config = config;
|
|
305
|
-
this.rpcClient = new RpcClient({
|
|
306
|
-
endpoint: config.rpcEndpoint ?? "https://api.devnet.solana.com",
|
|
307
|
-
commitment: config.commitment
|
|
308
|
-
});
|
|
309
|
-
this.isDevelopment = process.env.NODE_ENV === "development" || config.cluster === "localnet" || false;
|
|
310
|
-
}
|
|
311
|
-
/**
|
|
312
|
-
* Get singleton instance
|
|
313
|
-
*/
|
|
314
|
-
static getInstance(config) {
|
|
315
|
-
if (!_DevTools.instance && config) {
|
|
316
|
-
_DevTools.instance = new _DevTools(config);
|
|
317
|
-
}
|
|
318
|
-
if (!_DevTools.instance) {
|
|
319
|
-
throw new Error("DevTools not initialized. Call with config first.");
|
|
320
|
-
}
|
|
321
|
-
return _DevTools.instance;
|
|
322
|
-
}
|
|
323
|
-
/**
|
|
324
|
-
* Enable development mode
|
|
325
|
-
*/
|
|
326
|
-
enableDevMode() {
|
|
327
|
-
this.isDevelopment = true;
|
|
328
|
-
console.log("\u{1F6E0}\uFE0F GhostSpeak Development Mode Enabled");
|
|
329
|
-
console.log(" - Transaction simulation before sending");
|
|
330
|
-
console.log(" - Cost estimates for all operations");
|
|
331
|
-
console.log(" - Enhanced error messages");
|
|
332
|
-
console.log(" - Performance timing");
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Check if in development mode
|
|
336
|
-
*/
|
|
337
|
-
isDevMode() {
|
|
338
|
-
return this.isDevelopment;
|
|
339
|
-
}
|
|
340
|
-
/**
|
|
341
|
-
* Analyze transaction instructions
|
|
342
|
-
*/
|
|
343
|
-
analyzeTransaction(instructions) {
|
|
344
|
-
const writableAccounts = /* @__PURE__ */ new Set();
|
|
345
|
-
const readonlyAccounts = /* @__PURE__ */ new Set();
|
|
346
|
-
const signers = /* @__PURE__ */ new Set();
|
|
347
|
-
const warnings = [];
|
|
348
|
-
let totalSize = 64;
|
|
349
|
-
const instructionAnalyses = instructions.map((instr, index) => {
|
|
350
|
-
totalSize += 32;
|
|
351
|
-
totalSize += (instr.accounts?.length ?? 0) * 32;
|
|
352
|
-
totalSize += instr.data?.length ?? 0;
|
|
353
|
-
const accounts = (instr.accounts ?? []).map((acc) => {
|
|
354
|
-
const isWritable = acc.role.toString().includes("writable") || acc.role.toString().includes("WRITABLE") || acc.role === 1 || // AccountRole.WRITABLE = 1
|
|
355
|
-
acc.role === 3;
|
|
356
|
-
const isSigner = acc.role.toString().includes("signer") || acc.role.toString().includes("SIGNER") || typeof acc === "object" && "signer" in acc || acc.role === 3;
|
|
357
|
-
if (isWritable) {
|
|
358
|
-
writableAccounts.add(acc.address);
|
|
359
|
-
} else {
|
|
360
|
-
readonlyAccounts.add(acc.address);
|
|
361
|
-
}
|
|
362
|
-
if (isSigner) {
|
|
363
|
-
signers.add(acc.address);
|
|
364
|
-
}
|
|
365
|
-
return {
|
|
366
|
-
address: acc.address,
|
|
367
|
-
isWritable,
|
|
368
|
-
isSigner,
|
|
369
|
-
role: acc.role
|
|
370
|
-
};
|
|
371
|
-
});
|
|
372
|
-
const humanReadable = this.getInstructionDescription(instr, index);
|
|
373
|
-
return {
|
|
374
|
-
index,
|
|
375
|
-
programId: instr.programAddress,
|
|
376
|
-
accountCount: accounts.length,
|
|
377
|
-
dataSize: instr.data?.length ?? 0,
|
|
378
|
-
humanReadable,
|
|
379
|
-
accounts
|
|
380
|
-
};
|
|
381
|
-
});
|
|
382
|
-
const estimatedComputeUnits = this.estimateComputeUnits(instructions);
|
|
383
|
-
const estimatedFee = this.estimateFee(estimatedComputeUnits, instructions.length);
|
|
384
|
-
if (totalSize > 1232) {
|
|
385
|
-
warnings.push(`Transaction size (${totalSize} bytes) exceeds limit (1232 bytes)`);
|
|
386
|
-
}
|
|
387
|
-
if (signers.size === 0) {
|
|
388
|
-
warnings.push("No signers found in transaction");
|
|
389
|
-
}
|
|
390
|
-
if (estimatedComputeUnits > BigInt(14e5)) {
|
|
391
|
-
warnings.push(`High compute usage: ${estimatedComputeUnits} units`);
|
|
392
|
-
}
|
|
393
|
-
return {
|
|
394
|
-
instructions: instructionAnalyses,
|
|
395
|
-
totalAccounts: writableAccounts.size + readonlyAccounts.size,
|
|
396
|
-
signerCount: signers.size,
|
|
397
|
-
writableAccounts: Array.from(writableAccounts),
|
|
398
|
-
readonlyAccounts: Array.from(readonlyAccounts),
|
|
399
|
-
estimatedSize: totalSize,
|
|
400
|
-
estimatedComputeUnits,
|
|
401
|
-
estimatedFee,
|
|
402
|
-
warnings
|
|
403
|
-
};
|
|
404
|
-
}
|
|
405
|
-
/**
|
|
406
|
-
* Get human-readable instruction description
|
|
407
|
-
*/
|
|
408
|
-
getInstructionDescription(instruction, _index) {
|
|
409
|
-
const programId = instruction.programAddress;
|
|
410
|
-
if (programId === this.config.programId) {
|
|
411
|
-
return this.decodeGhostSpeakInstruction(instruction);
|
|
412
|
-
}
|
|
413
|
-
if (programId === "11111111111111111111111111111111") {
|
|
414
|
-
return "System Program: Transfer or Create Account";
|
|
415
|
-
}
|
|
416
|
-
if (programId === "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA") {
|
|
417
|
-
return "Token Program: Token Operation";
|
|
418
|
-
}
|
|
419
|
-
if (programId === "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb") {
|
|
420
|
-
return "Token-2022 Program: Advanced Token Operation";
|
|
421
|
-
}
|
|
422
|
-
return `Unknown Instruction`;
|
|
423
|
-
}
|
|
424
|
-
/**
|
|
425
|
-
* Decode GhostSpeak instruction
|
|
426
|
-
*/
|
|
427
|
-
decodeGhostSpeakInstruction(instruction) {
|
|
428
|
-
if (!instruction.data || instruction.data.length < 8) {
|
|
429
|
-
return "GhostSpeak: Unknown Instruction";
|
|
430
|
-
}
|
|
431
|
-
const discriminator = Array.from(instruction.data.slice(0, 8)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
432
|
-
const instructionMap = {
|
|
433
|
-
"a8c5e109d3d1b8d5": "Register Agent",
|
|
434
|
-
"b7f3c8e0a2d4e9f1": "Create Escrow",
|
|
435
|
-
"c4d2f7a9b8e1c3f5": "Send Message",
|
|
436
|
-
"d9e8f2b5c1a7e4f8": "Create Channel"
|
|
437
|
-
// Add more mappings as needed
|
|
438
|
-
};
|
|
439
|
-
return `GhostSpeak: ${instructionMap[discriminator] ?? "Custom Instruction"}`;
|
|
440
|
-
}
|
|
441
|
-
/**
|
|
442
|
-
* Estimate compute units for instructions
|
|
443
|
-
*/
|
|
444
|
-
estimateComputeUnits(instructions) {
|
|
445
|
-
let totalUnits = BigInt(0);
|
|
446
|
-
for (const instr of instructions) {
|
|
447
|
-
totalUnits += BigInt(200);
|
|
448
|
-
totalUnits += BigInt((instr.accounts?.length ?? 0) * 150);
|
|
449
|
-
totalUnits += BigInt((instr.data?.length ?? 0) * 10);
|
|
450
|
-
if (instr.programAddress === this.config.programId) {
|
|
451
|
-
totalUnits += BigInt(5e3);
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
return totalUnits;
|
|
455
|
-
}
|
|
456
|
-
/**
|
|
457
|
-
* Estimate transaction fee
|
|
458
|
-
*/
|
|
459
|
-
estimateFee(computeUnits, instructionCount) {
|
|
460
|
-
const baseFee = BigInt(5e3);
|
|
461
|
-
const computeFee = computeUnits * BigInt(5) / BigInt(1e6);
|
|
462
|
-
const priorityFee = BigInt(instructionCount * 1e3);
|
|
463
|
-
return baseFee + computeFee + priorityFee;
|
|
464
|
-
}
|
|
465
|
-
/**
|
|
466
|
-
* Log debug message
|
|
467
|
-
*/
|
|
468
|
-
log(message, data) {
|
|
469
|
-
if (!this.isDevelopment) return;
|
|
470
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
471
|
-
const logEntry = `[${timestamp}] ${message}`;
|
|
472
|
-
this.logs.push(logEntry);
|
|
473
|
-
console.log(`\u{1F50D} ${logEntry}`);
|
|
474
|
-
if (data) {
|
|
475
|
-
console.log(" Data:", data);
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
/**
|
|
479
|
-
* Start timing an operation
|
|
480
|
-
*/
|
|
481
|
-
startTiming(label) {
|
|
482
|
-
if (!this.isDevelopment) return;
|
|
483
|
-
const perfNow = typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
484
|
-
this.timings.set(label, perfNow);
|
|
485
|
-
}
|
|
486
|
-
/**
|
|
487
|
-
* End timing and log result
|
|
488
|
-
*/
|
|
489
|
-
endTiming(label) {
|
|
490
|
-
if (!this.isDevelopment) return;
|
|
491
|
-
const start = this.timings.get(label);
|
|
492
|
-
if (!start) return;
|
|
493
|
-
const perfNow = typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
494
|
-
const duration = perfNow - start;
|
|
495
|
-
this.log(`${label} took ${duration.toFixed(2)}ms`);
|
|
496
|
-
this.timings.delete(label);
|
|
497
|
-
}
|
|
498
|
-
/**
|
|
499
|
-
* Format transaction for display
|
|
500
|
-
*/
|
|
501
|
-
formatTransaction(analysis) {
|
|
502
|
-
const lines = [
|
|
503
|
-
"\u{1F4CB} Transaction Analysis",
|
|
504
|
-
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550",
|
|
505
|
-
`Instructions: ${analysis.instructions.length}`,
|
|
506
|
-
`Total Accounts: ${analysis.totalAccounts}`,
|
|
507
|
-
`Signers: ${analysis.signerCount}`,
|
|
508
|
-
`Estimated Size: ${analysis.estimatedSize} bytes`,
|
|
509
|
-
`Estimated Compute Units: ${analysis.estimatedComputeUnits.toLocaleString()}`,
|
|
510
|
-
`Estimated Fee: ${(Number(analysis.estimatedFee) / 1e9).toFixed(6)} SOL`,
|
|
511
|
-
""
|
|
512
|
-
];
|
|
513
|
-
lines.push("Instructions:");
|
|
514
|
-
for (const instr of analysis.instructions) {
|
|
515
|
-
lines.push(` ${instr.index + 1}. ${instr.humanReadable}`);
|
|
516
|
-
lines.push(` Program: ${instr.programId.slice(0, 8)}...`);
|
|
517
|
-
lines.push(` Accounts: ${instr.accountCount}, Data: ${instr.dataSize} bytes`);
|
|
518
|
-
}
|
|
519
|
-
if (analysis.warnings.length > 0) {
|
|
520
|
-
lines.push("");
|
|
521
|
-
lines.push("\u26A0\uFE0F Warnings:");
|
|
522
|
-
for (const warning of analysis.warnings) {
|
|
523
|
-
lines.push(` - ${warning}`);
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
lines.push("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
527
|
-
return lines.join("\n");
|
|
528
|
-
}
|
|
529
|
-
/**
|
|
530
|
-
* Export debug logs
|
|
531
|
-
*/
|
|
532
|
-
exportLogs() {
|
|
533
|
-
return [...this.logs];
|
|
534
|
-
}
|
|
535
|
-
/**
|
|
536
|
-
* Clear debug logs
|
|
537
|
-
*/
|
|
538
|
-
clearLogs() {
|
|
539
|
-
this.logs = [];
|
|
540
|
-
this.timings.clear();
|
|
541
|
-
}
|
|
542
|
-
};
|
|
543
|
-
function validateInstruction(instruction) {
|
|
544
|
-
const inst = instruction;
|
|
545
|
-
if (!inst.programAddress) {
|
|
546
|
-
throw new Error("Invalid instruction format");
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
var InstructionBuilder = class {
|
|
550
|
-
rpcClient;
|
|
551
|
-
config;
|
|
552
|
-
devTools;
|
|
553
|
-
debugMode = false;
|
|
554
|
-
constructor(config) {
|
|
555
|
-
this.config = config;
|
|
556
|
-
this.rpcClient = new RpcClient({
|
|
557
|
-
endpoint: config.rpcEndpoint ?? "https://api.devnet.solana.com",
|
|
558
|
-
wsEndpoint: config.wsEndpoint,
|
|
559
|
-
commitment: config.commitment ?? "confirmed"
|
|
560
|
-
});
|
|
561
|
-
this.devTools = DevTools.getInstance(config);
|
|
562
|
-
}
|
|
563
|
-
/**
|
|
564
|
-
* Execute a single instruction with unified error handling and transaction patterns
|
|
565
|
-
*/
|
|
566
|
-
async execute(instructionName, instructionGetter, signers, options) {
|
|
567
|
-
const context = createErrorContext(
|
|
568
|
-
"execute",
|
|
569
|
-
instructionName,
|
|
570
|
-
signers.map((s) => ({ address: s.address, name: "signer" })),
|
|
571
|
-
{ programId: this.config.programId }
|
|
572
|
-
);
|
|
573
|
-
try {
|
|
574
|
-
if (this.devTools.isDevMode()) {
|
|
575
|
-
this.devTools.startTiming(instructionName);
|
|
576
|
-
}
|
|
577
|
-
const instruction = await Promise.resolve(instructionGetter());
|
|
578
|
-
validateInstruction(instruction);
|
|
579
|
-
if (this.debugMode || this.devTools.isDevMode()) {
|
|
580
|
-
const analysis = this.devTools.analyzeTransaction([instruction]);
|
|
581
|
-
console.log(this.devTools.formatTransaction(analysis));
|
|
582
|
-
this.debugMode = false;
|
|
583
|
-
}
|
|
584
|
-
if (options?.simulate) {
|
|
585
|
-
return await this.simulateInstruction(instruction, signers);
|
|
586
|
-
}
|
|
587
|
-
const latestBlockhashResult = await this.rpcClient.getLatestBlockhash();
|
|
588
|
-
const latestBlockhash = {
|
|
589
|
-
blockhash: latestBlockhashResult.blockhash,
|
|
590
|
-
lastValidBlockHeight: latestBlockhashResult.lastValidBlockHeight
|
|
591
|
-
};
|
|
592
|
-
const transactionMessage = pipe(
|
|
593
|
-
createTransactionMessage({ version: 0 }),
|
|
594
|
-
(tx) => setTransactionMessageFeePayerSigner(signers[0], tx),
|
|
595
|
-
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
|
|
596
|
-
(tx) => appendTransactionMessageInstructions([instruction], tx)
|
|
597
|
-
);
|
|
598
|
-
const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);
|
|
599
|
-
const signatureResult = await this.sendAndConfirm(
|
|
600
|
-
signedTransaction,
|
|
601
|
-
options?.skipPreflight ?? false,
|
|
602
|
-
options?.maxRetries ?? 30
|
|
603
|
-
);
|
|
604
|
-
if (typeof signatureResult !== "string") {
|
|
605
|
-
throw new Error("Transaction signature is not a string");
|
|
606
|
-
}
|
|
607
|
-
const signature = signatureResult;
|
|
608
|
-
if (options?.returnDetails) {
|
|
609
|
-
const cluster = this.config.cluster ?? "devnet";
|
|
610
|
-
const result = createTransactionResult(signature, cluster, this.config.commitment ?? "confirmed");
|
|
611
|
-
if (this.devTools.isDevMode()) {
|
|
612
|
-
this.devTools.endTiming(instructionName);
|
|
613
|
-
}
|
|
614
|
-
return result;
|
|
615
|
-
}
|
|
616
|
-
if (this.devTools.isDevMode()) {
|
|
617
|
-
this.devTools.endTiming(instructionName);
|
|
618
|
-
}
|
|
619
|
-
return signature;
|
|
620
|
-
} catch (error) {
|
|
621
|
-
logEnhancedError(error, context);
|
|
622
|
-
throw error;
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
/**
|
|
626
|
-
* Execute multiple instructions in a single transaction
|
|
627
|
-
*/
|
|
628
|
-
async executeBatch(batchName, instructionGetters, signers, options) {
|
|
629
|
-
const context = createErrorContext(
|
|
630
|
-
"executeBatch",
|
|
631
|
-
batchName,
|
|
632
|
-
signers.map((s) => ({ address: s.address, name: "signer" })),
|
|
633
|
-
{ programId: this.config.programId, instructionCount: instructionGetters.length }
|
|
634
|
-
);
|
|
635
|
-
try {
|
|
636
|
-
const instructions = await Promise.all(
|
|
637
|
-
instructionGetters.map(async (getter, i) => {
|
|
638
|
-
const instruction = await Promise.resolve(getter());
|
|
639
|
-
try {
|
|
640
|
-
validateInstruction(instruction);
|
|
641
|
-
return instruction;
|
|
642
|
-
} catch (error) {
|
|
643
|
-
throw new Error(`Instruction ${i} in ${batchName}: ${error.message}`);
|
|
644
|
-
}
|
|
645
|
-
})
|
|
646
|
-
);
|
|
647
|
-
const estimatedSize = this.estimateTransactionSize(instructions);
|
|
648
|
-
if (estimatedSize > 1232) {
|
|
649
|
-
throw new Error(`Transaction too large: ${estimatedSize} bytes (max: 1232)`);
|
|
650
|
-
}
|
|
651
|
-
if (options?.simulate) {
|
|
652
|
-
return await this.simulateBatch(instructions, signers);
|
|
653
|
-
}
|
|
654
|
-
const latestBlockhashResult = await this.rpcClient.getLatestBlockhash();
|
|
655
|
-
const latestBlockhash = {
|
|
656
|
-
blockhash: latestBlockhashResult.blockhash,
|
|
657
|
-
lastValidBlockHeight: latestBlockhashResult.lastValidBlockHeight
|
|
658
|
-
};
|
|
659
|
-
const transactionMessage = pipe(
|
|
660
|
-
createTransactionMessage({ version: 0 }),
|
|
661
|
-
(tx) => setTransactionMessageFeePayerSigner(signers[0], tx),
|
|
662
|
-
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
|
|
663
|
-
(tx) => appendTransactionMessageInstructions(instructions, tx)
|
|
664
|
-
);
|
|
665
|
-
const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);
|
|
666
|
-
const signatureResult = await this.sendAndConfirm(
|
|
667
|
-
signedTransaction,
|
|
668
|
-
options?.skipPreflight ?? false
|
|
669
|
-
);
|
|
670
|
-
if (typeof signatureResult !== "string") {
|
|
671
|
-
throw new Error("Transaction signature is not a string");
|
|
672
|
-
}
|
|
673
|
-
const signature = signatureResult;
|
|
674
|
-
if (options?.returnDetails) {
|
|
675
|
-
const cluster = this.config.cluster ?? "devnet";
|
|
676
|
-
const result = createTransactionResult(signature, cluster, this.config.commitment ?? "confirmed");
|
|
677
|
-
if (this.devTools.isDevMode()) {
|
|
678
|
-
this.devTools.endTiming(batchName);
|
|
679
|
-
}
|
|
680
|
-
return result;
|
|
681
|
-
}
|
|
682
|
-
if (this.devTools.isDevMode()) {
|
|
683
|
-
this.devTools.endTiming(batchName);
|
|
684
|
-
}
|
|
685
|
-
return signature;
|
|
686
|
-
} catch (error) {
|
|
687
|
-
logEnhancedError(error, context);
|
|
688
|
-
throw error;
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
/**
|
|
692
|
-
* Get and decode account data with unified error handling
|
|
693
|
-
*/
|
|
694
|
-
async getAccount(address2, decoderImportName) {
|
|
695
|
-
try {
|
|
696
|
-
const accountInfo = await this.rpcClient.getAccountInfo(address2, {
|
|
697
|
-
commitment: this.config.commitment
|
|
698
|
-
});
|
|
699
|
-
if (!accountInfo) return null;
|
|
700
|
-
const generated = await import('./generated-VNLHMR6Y.js');
|
|
701
|
-
const decoderGetter = generated[decoderImportName];
|
|
702
|
-
const decoder = decoderGetter();
|
|
703
|
-
const rawData = this.extractRawData(accountInfo.data);
|
|
704
|
-
return decoder.decode(rawData);
|
|
705
|
-
} catch (error) {
|
|
706
|
-
console.warn(`Failed to fetch account ${address2}:`, error);
|
|
707
|
-
return null;
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
/**
|
|
711
|
-
* Get multiple accounts with unified pattern
|
|
712
|
-
*/
|
|
713
|
-
async getAccounts(addresses, decoderImportName) {
|
|
714
|
-
try {
|
|
715
|
-
const accounts = await this.rpcClient.getMultipleAccounts(addresses, {
|
|
716
|
-
commitment: this.config.commitment
|
|
717
|
-
});
|
|
718
|
-
const generated = await import('./generated-VNLHMR6Y.js');
|
|
719
|
-
const decoderGetter = generated[decoderImportName];
|
|
720
|
-
const decoder = decoderGetter();
|
|
721
|
-
return accounts.map((accountInfo) => {
|
|
722
|
-
if (!accountInfo) return null;
|
|
723
|
-
try {
|
|
724
|
-
const rawData = this.extractRawData(accountInfo.data);
|
|
725
|
-
return decoder.decode(rawData);
|
|
726
|
-
} catch {
|
|
727
|
-
return null;
|
|
728
|
-
}
|
|
729
|
-
});
|
|
730
|
-
} catch (error) {
|
|
731
|
-
console.warn("Failed to fetch multiple accounts:", error);
|
|
732
|
-
return addresses.map(() => null);
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
/**
|
|
736
|
-
* Get program accounts with filters
|
|
737
|
-
*/
|
|
738
|
-
async getProgramAccounts(decoderImportName, filters) {
|
|
739
|
-
try {
|
|
740
|
-
const convertedFilters = filters?.map((filter) => {
|
|
741
|
-
if ("dataSize" in filter) {
|
|
742
|
-
return { dataSize: filter.dataSize };
|
|
743
|
-
} else {
|
|
744
|
-
const encoding = filter.memcmp.encoding ?? "base58";
|
|
745
|
-
if (encoding === "base64") {
|
|
746
|
-
return {
|
|
747
|
-
memcmp: {
|
|
748
|
-
offset: filter.memcmp.offset,
|
|
749
|
-
bytes: filter.memcmp.bytes,
|
|
750
|
-
encoding: "base64"
|
|
751
|
-
}
|
|
752
|
-
};
|
|
753
|
-
} else {
|
|
754
|
-
return {
|
|
755
|
-
memcmp: {
|
|
756
|
-
offset: filter.memcmp.offset,
|
|
757
|
-
bytes: filter.memcmp.bytes,
|
|
758
|
-
encoding: "base58"
|
|
759
|
-
}
|
|
760
|
-
};
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
});
|
|
764
|
-
const accounts = await this.rpcClient.getProgramAccounts(this.config.programId, {
|
|
765
|
-
commitment: this.config.commitment,
|
|
766
|
-
filters: convertedFilters ?? []
|
|
767
|
-
});
|
|
768
|
-
const generated = await import('./generated-VNLHMR6Y.js');
|
|
769
|
-
const decoderGetter = generated[decoderImportName];
|
|
770
|
-
const decoder = decoderGetter();
|
|
771
|
-
const decodedAccounts = [];
|
|
772
|
-
for (const { pubkey, account } of accounts) {
|
|
773
|
-
try {
|
|
774
|
-
const rawData = this.extractRawData(account.data);
|
|
775
|
-
const decodedData = decoder.decode(rawData);
|
|
776
|
-
decodedAccounts.push({ address: pubkey, data: decodedData });
|
|
777
|
-
} catch {
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
return decodedAccounts;
|
|
781
|
-
} catch (error) {
|
|
782
|
-
console.error("Failed to get program accounts:", error);
|
|
783
|
-
return [];
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
/**
|
|
787
|
-
* Enable debug mode for next transaction
|
|
788
|
-
*/
|
|
789
|
-
enableDebug() {
|
|
790
|
-
this.debugMode = true;
|
|
791
|
-
return this;
|
|
792
|
-
}
|
|
793
|
-
/**
|
|
794
|
-
* Debug transaction - analyze without executing
|
|
795
|
-
*/
|
|
796
|
-
async debug(instructionName, instructionGetters) {
|
|
797
|
-
this.devTools.log(`Debugging ${instructionName}`);
|
|
798
|
-
const instructions = await Promise.all(
|
|
799
|
-
instructionGetters.map(async (getter) => {
|
|
800
|
-
const instruction = await Promise.resolve(getter());
|
|
801
|
-
validateInstruction(instruction);
|
|
802
|
-
return instruction;
|
|
803
|
-
})
|
|
804
|
-
);
|
|
805
|
-
const analysis = this.devTools.analyzeTransaction(instructions);
|
|
806
|
-
console.log(this.devTools.formatTransaction(analysis));
|
|
807
|
-
return analysis;
|
|
808
|
-
}
|
|
809
|
-
/**
|
|
810
|
-
* Get human-readable explanation of transaction
|
|
811
|
-
*/
|
|
812
|
-
async explain(instructionName, instructionGetters) {
|
|
813
|
-
const analysis = await this.debug(instructionName, instructionGetters);
|
|
814
|
-
const lines = [
|
|
815
|
-
`\u{1F50D} Transaction: ${instructionName}`,
|
|
816
|
-
"",
|
|
817
|
-
"This transaction will:",
|
|
818
|
-
...analysis.instructions.map((instr, i) => ` ${i + 1}. ${instr.humanReadable}`),
|
|
819
|
-
"",
|
|
820
|
-
`Cost: ~${(Number(analysis.estimatedFee) / 1e9).toFixed(6)} SOL`,
|
|
821
|
-
`Size: ${analysis.estimatedSize} bytes`,
|
|
822
|
-
`Compute: ${analysis.estimatedComputeUnits.toLocaleString()} units`
|
|
823
|
-
];
|
|
824
|
-
if (analysis.warnings.length > 0) {
|
|
825
|
-
lines.push("", "\u26A0\uFE0F Warnings:");
|
|
826
|
-
lines.push(...analysis.warnings.map((w) => ` - ${w}`));
|
|
827
|
-
}
|
|
828
|
-
return lines.join("\n");
|
|
829
|
-
}
|
|
830
|
-
/**
|
|
831
|
-
* Estimate transaction cost
|
|
832
|
-
*/
|
|
833
|
-
async estimateCost(instructionGetters) {
|
|
834
|
-
try {
|
|
835
|
-
const instructions = await Promise.all(
|
|
836
|
-
instructionGetters.map(async (getter) => {
|
|
837
|
-
const instruction = await Promise.resolve(getter());
|
|
838
|
-
validateInstruction(instruction);
|
|
839
|
-
return instruction;
|
|
840
|
-
})
|
|
841
|
-
);
|
|
842
|
-
const latestBlockhashResult = await this.rpcClient.getLatestBlockhash();
|
|
843
|
-
const latestBlockhash = {
|
|
844
|
-
blockhash: latestBlockhashResult.blockhash,
|
|
845
|
-
lastValidBlockHeight: latestBlockhashResult.lastValidBlockHeight
|
|
846
|
-
};
|
|
847
|
-
const transactionMessage = pipe(
|
|
848
|
-
createTransactionMessage({ version: 0 }),
|
|
849
|
-
(tx) => setTransactionMessageFeePayer(this.config.defaultFeePayer, tx),
|
|
850
|
-
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
|
|
851
|
-
(tx) => appendTransactionMessageInstructions(instructions, tx)
|
|
852
|
-
);
|
|
853
|
-
const compiledMessage = compileTransactionMessage(transactionMessage);
|
|
854
|
-
const encodedMessage = Buffer.from(compiledMessage).toString("base64");
|
|
855
|
-
const fee = await this.rpcClient.getFeeForMessage(encodedMessage);
|
|
856
|
-
return BigInt(fee ?? 0);
|
|
857
|
-
} catch {
|
|
858
|
-
const baseFee = 5000n;
|
|
859
|
-
const perInstructionFee = 1000n;
|
|
860
|
-
return baseFee + BigInt(instructionGetters.length) * perInstructionFee;
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
// Private helper methods
|
|
864
|
-
async sendAndConfirm(signedTransaction, skipPreflight, maxRetries = 30) {
|
|
865
|
-
const wireTransaction = getBase64EncodedWireTransaction(signedTransaction);
|
|
866
|
-
const signature = await this.rpcClient.sendTransaction(wireTransaction, {
|
|
867
|
-
skipPreflight,
|
|
868
|
-
preflightCommitment: this.config.commitment
|
|
869
|
-
});
|
|
870
|
-
console.log("\u{1F50D} Transaction sent, signature:", signature);
|
|
871
|
-
console.log("\u{1F50D} Signature length:", signature.length);
|
|
872
|
-
console.log("\u{1F50D} Signature type:", typeof signature);
|
|
873
|
-
let confirmed = false;
|
|
874
|
-
let attempts = 0;
|
|
875
|
-
let currentDelay = 1e3;
|
|
876
|
-
const maxConfirmationTime = 3e4;
|
|
877
|
-
const startTime = Date.now();
|
|
878
|
-
while (!confirmed && attempts < maxRetries && Date.now() - startTime < maxConfirmationTime) {
|
|
879
|
-
try {
|
|
880
|
-
console.log(`\u{1F50D} Confirmation attempt ${attempts + 1}/${maxRetries}`);
|
|
881
|
-
const statuses = await this.rpcClient.getSignatureStatuses([signature]);
|
|
882
|
-
if (statuses[0]) {
|
|
883
|
-
console.log("\u{1F50D} Status found:", statuses[0]);
|
|
884
|
-
if (statuses[0].err) {
|
|
885
|
-
throw new Error(`Transaction failed: ${JSON.stringify(statuses[0].err, (_, v) => typeof v === "bigint" ? v.toString() : v)}`);
|
|
886
|
-
}
|
|
887
|
-
const confirmationStatus = statuses[0].confirmationStatus;
|
|
888
|
-
if (confirmationStatus === this.config.commitment || this.config.commitment === "confirmed" && confirmationStatus === "finalized") {
|
|
889
|
-
confirmed = true;
|
|
890
|
-
console.log("\u2705 Transaction confirmed via status check");
|
|
891
|
-
break;
|
|
892
|
-
}
|
|
893
|
-
} else {
|
|
894
|
-
console.log("\u{1F50D} No status found, trying transaction details...");
|
|
895
|
-
try {
|
|
896
|
-
const { createSolanaRpc: createSolanaRpc2 } = await import('@solana/kit');
|
|
897
|
-
const directRpc = createSolanaRpc2(this.config.rpcEndpoint ?? "https://api.devnet.solana.com");
|
|
898
|
-
const transaction = await directRpc.getTransaction(signature, {
|
|
899
|
-
commitment: this.config.commitment ?? "confirmed",
|
|
900
|
-
encoding: "json",
|
|
901
|
-
maxSupportedTransactionVersion: 0
|
|
902
|
-
}).send();
|
|
903
|
-
if (transaction && transaction.meta) {
|
|
904
|
-
if (transaction.meta.err) {
|
|
905
|
-
throw new Error(`Transaction failed: ${JSON.stringify(transaction.meta.err, (_, v) => typeof v === "bigint" ? v.toString() : v)}`);
|
|
906
|
-
}
|
|
907
|
-
confirmed = true;
|
|
908
|
-
console.log("\u2705 Transaction confirmed via direct lookup");
|
|
909
|
-
break;
|
|
910
|
-
}
|
|
911
|
-
} catch {
|
|
912
|
-
console.log("\u{1F50D} Transaction details not yet available");
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
attempts++;
|
|
916
|
-
await new Promise((resolve) => setTimeout(resolve, currentDelay));
|
|
917
|
-
currentDelay = Math.min(currentDelay * 1.5, 5e3);
|
|
918
|
-
} catch (error) {
|
|
919
|
-
if (error instanceof Error && error.message.includes("Transaction failed")) {
|
|
920
|
-
throw error;
|
|
921
|
-
}
|
|
922
|
-
console.log(`\u{1F50D} Confirmation attempt failed:`, error.message);
|
|
923
|
-
attempts++;
|
|
924
|
-
await new Promise((resolve) => setTimeout(resolve, currentDelay * 2));
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
if (!confirmed) {
|
|
928
|
-
console.log("\u{1F50D} Final confirmation attempt via transaction lookup...");
|
|
929
|
-
try {
|
|
930
|
-
const { createSolanaRpc: createSolanaRpc2 } = await import('@solana/kit');
|
|
931
|
-
const directRpc = createSolanaRpc2(this.config.rpcEndpoint ?? "https://api.devnet.solana.com");
|
|
932
|
-
const transaction = await directRpc.getTransaction(signature, {
|
|
933
|
-
commitment: this.config.commitment ?? "confirmed",
|
|
934
|
-
encoding: "json",
|
|
935
|
-
maxSupportedTransactionVersion: 0
|
|
936
|
-
}).send();
|
|
937
|
-
if (transaction && transaction.meta) {
|
|
938
|
-
if (transaction.meta.err) {
|
|
939
|
-
throw new Error(`Transaction failed: ${JSON.stringify(transaction.meta.err, (_, v) => typeof v === "bigint" ? v.toString() : v)}`);
|
|
940
|
-
}
|
|
941
|
-
console.log("\u2705 Transaction confirmed on final check - returning success");
|
|
942
|
-
return signature;
|
|
943
|
-
}
|
|
944
|
-
} catch (finalError) {
|
|
945
|
-
console.log("\u{1F50D} Final check failed:", finalError.message);
|
|
946
|
-
}
|
|
947
|
-
console.log("\u26A0\uFE0F Transaction confirmation timed out, but transaction was sent");
|
|
948
|
-
console.log(` Check status at: https://explorer.solana.com/tx/${signature}?cluster=${this.config.cluster || "devnet"}`);
|
|
949
|
-
return signature;
|
|
950
|
-
}
|
|
951
|
-
return signature;
|
|
952
|
-
}
|
|
953
|
-
async simulateInstruction(instruction, signers) {
|
|
954
|
-
const latestBlockhashResult = await this.rpcClient.getLatestBlockhash();
|
|
955
|
-
const latestBlockhash = {
|
|
956
|
-
blockhash: latestBlockhashResult.blockhash,
|
|
957
|
-
lastValidBlockHeight: latestBlockhashResult.lastValidBlockHeight
|
|
958
|
-
};
|
|
959
|
-
const transactionMessage = pipe(
|
|
960
|
-
createTransactionMessage({ version: 0 }),
|
|
961
|
-
(tx) => setTransactionMessageFeePayerSigner(signers[0], tx),
|
|
962
|
-
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
|
|
963
|
-
(tx) => appendTransactionMessageInstructions([instruction], tx)
|
|
964
|
-
);
|
|
965
|
-
const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);
|
|
966
|
-
const wireTransaction = getBase64EncodedWireTransaction(signedTransaction);
|
|
967
|
-
return this.rpcClient.simulateTransaction(wireTransaction, {
|
|
968
|
-
commitment: this.config.commitment,
|
|
969
|
-
replaceRecentBlockhash: true
|
|
970
|
-
});
|
|
971
|
-
}
|
|
972
|
-
async simulateBatch(instructions, signers) {
|
|
973
|
-
const latestBlockhashResult = await this.rpcClient.getLatestBlockhash();
|
|
974
|
-
const latestBlockhash = {
|
|
975
|
-
blockhash: latestBlockhashResult.blockhash,
|
|
976
|
-
lastValidBlockHeight: latestBlockhashResult.lastValidBlockHeight
|
|
977
|
-
};
|
|
978
|
-
const transactionMessage = pipe(
|
|
979
|
-
createTransactionMessage({ version: 0 }),
|
|
980
|
-
(tx) => setTransactionMessageFeePayerSigner(signers[0], tx),
|
|
981
|
-
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
|
|
982
|
-
(tx) => appendTransactionMessageInstructions(instructions, tx)
|
|
983
|
-
);
|
|
984
|
-
const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);
|
|
985
|
-
const wireTransaction = getBase64EncodedWireTransaction(signedTransaction);
|
|
986
|
-
return this.rpcClient.simulateTransaction(wireTransaction, {
|
|
987
|
-
commitment: this.config.commitment,
|
|
988
|
-
replaceRecentBlockhash: true
|
|
989
|
-
});
|
|
990
|
-
}
|
|
991
|
-
estimateTransactionSize(instructions) {
|
|
992
|
-
let totalSize = 64;
|
|
993
|
-
for (const instruction of instructions) {
|
|
994
|
-
totalSize += 32;
|
|
995
|
-
totalSize += (instruction.accounts?.length ?? 0) * 32;
|
|
996
|
-
totalSize += instruction.data.length;
|
|
997
|
-
}
|
|
998
|
-
return totalSize;
|
|
999
|
-
}
|
|
1000
|
-
extractRawData(data) {
|
|
1001
|
-
if (Buffer.isBuffer(data) || data instanceof Uint8Array) {
|
|
1002
|
-
return new Uint8Array(data);
|
|
1003
|
-
}
|
|
1004
|
-
if (typeof data === "object" && data !== null && "data" in data) {
|
|
1005
|
-
return Buffer.from(data.data, "base64");
|
|
1006
|
-
}
|
|
1007
|
-
if (typeof data === "string") {
|
|
1008
|
-
return Buffer.from(data, "base64");
|
|
1009
|
-
}
|
|
1010
|
-
throw new Error("Invalid account data format");
|
|
1011
|
-
}
|
|
1012
|
-
// =====================================================
|
|
1013
|
-
// H2A PROTOCOL INSTRUCTION METHODS
|
|
1014
|
-
// =====================================================
|
|
1015
|
-
/**
|
|
1016
|
-
* Create a communication session instruction
|
|
1017
|
-
*/
|
|
1018
|
-
async createCommunicationSession(_params) {
|
|
1019
|
-
return {
|
|
1020
|
-
programAddress: this.config.programId,
|
|
1021
|
-
accounts: [],
|
|
1022
|
-
data: new Uint8Array(0)
|
|
1023
|
-
// Placeholder - would contain serialized instruction data
|
|
1024
|
-
};
|
|
1025
|
-
}
|
|
1026
|
-
/**
|
|
1027
|
-
* Send a communication message instruction
|
|
1028
|
-
*/
|
|
1029
|
-
async sendCommunicationMessage(_sessionAddress, _params) {
|
|
1030
|
-
return {
|
|
1031
|
-
programAddress: this.config.programId,
|
|
1032
|
-
accounts: [],
|
|
1033
|
-
data: new Uint8Array(0)
|
|
1034
|
-
// Placeholder - would contain serialized instruction data
|
|
1035
|
-
};
|
|
1036
|
-
}
|
|
1037
|
-
/**
|
|
1038
|
-
* Update participant status instruction
|
|
1039
|
-
*/
|
|
1040
|
-
async updateParticipantStatus(_params) {
|
|
1041
|
-
return {
|
|
1042
|
-
programAddress: this.config.programId,
|
|
1043
|
-
accounts: [],
|
|
1044
|
-
data: new Uint8Array(0)
|
|
1045
|
-
// Placeholder - would contain serialized instruction data
|
|
1046
|
-
};
|
|
1047
|
-
}
|
|
1048
|
-
};
|
|
1049
|
-
|
|
1050
|
-
// src/core/BaseModule.ts
|
|
1051
|
-
var BaseModule = class {
|
|
1052
|
-
builder;
|
|
1053
|
-
config;
|
|
1054
|
-
_debugMode = false;
|
|
1055
|
-
constructor(config) {
|
|
1056
|
-
this.config = config;
|
|
1057
|
-
this.builder = new InstructionBuilder(config);
|
|
1058
|
-
}
|
|
1059
|
-
/**
|
|
1060
|
-
* Enable debug mode for next operation
|
|
1061
|
-
*/
|
|
1062
|
-
debug() {
|
|
1063
|
-
this._debugMode = true;
|
|
1064
|
-
this.builder.enableDebug();
|
|
1065
|
-
return this;
|
|
1066
|
-
}
|
|
1067
|
-
/**
|
|
1068
|
-
* Execute a single instruction
|
|
1069
|
-
*/
|
|
1070
|
-
async execute(instructionName, instructionGetter, signers) {
|
|
1071
|
-
return this.builder.execute(
|
|
1072
|
-
instructionName,
|
|
1073
|
-
instructionGetter,
|
|
1074
|
-
signers
|
|
1075
|
-
);
|
|
1076
|
-
}
|
|
1077
|
-
/**
|
|
1078
|
-
* Execute a single instruction with detailed result
|
|
1079
|
-
*/
|
|
1080
|
-
async executeWithDetails(instructionName, instructionGetter, signers) {
|
|
1081
|
-
return this.builder.execute(
|
|
1082
|
-
instructionName,
|
|
1083
|
-
instructionGetter,
|
|
1084
|
-
signers,
|
|
1085
|
-
{ returnDetails: true }
|
|
1086
|
-
);
|
|
1087
|
-
}
|
|
1088
|
-
/**
|
|
1089
|
-
* Execute multiple instructions in a batch
|
|
1090
|
-
*/
|
|
1091
|
-
async executeBatch(batchName, instructionGetters, signers) {
|
|
1092
|
-
return this.builder.executeBatch(
|
|
1093
|
-
batchName,
|
|
1094
|
-
instructionGetters.map((getter) => () => Promise.resolve(getter())),
|
|
1095
|
-
signers
|
|
1096
|
-
);
|
|
1097
|
-
}
|
|
1098
|
-
/**
|
|
1099
|
-
* Simulate an instruction
|
|
1100
|
-
*/
|
|
1101
|
-
async simulate(instructionName, instructionGetter, signers) {
|
|
1102
|
-
return this.builder.execute(
|
|
1103
|
-
instructionName,
|
|
1104
|
-
() => Promise.resolve(instructionGetter()),
|
|
1105
|
-
signers,
|
|
1106
|
-
{ simulate: true }
|
|
1107
|
-
);
|
|
1108
|
-
}
|
|
1109
|
-
/**
|
|
1110
|
-
* Simulate an instruction (public accessor)
|
|
1111
|
-
*/
|
|
1112
|
-
async simulateInstruction(instructionName, instructionGetter, signers) {
|
|
1113
|
-
return this.simulate(instructionName, instructionGetter, signers);
|
|
1114
|
-
}
|
|
1115
|
-
/**
|
|
1116
|
-
* Estimate transaction cost
|
|
1117
|
-
*/
|
|
1118
|
-
async estimateCost(instructionGetters) {
|
|
1119
|
-
return this.builder.estimateCost(instructionGetters);
|
|
1120
|
-
}
|
|
1121
|
-
/**
|
|
1122
|
-
* Get cost estimation for an instruction
|
|
1123
|
-
*/
|
|
1124
|
-
async getCost(instructionName, instructionGetter) {
|
|
1125
|
-
return this.builder.estimateCost([instructionGetter]);
|
|
1126
|
-
}
|
|
1127
|
-
/**
|
|
1128
|
-
* Get human-readable explanation
|
|
1129
|
-
*/
|
|
1130
|
-
async explain(instructionName, instructionGetter) {
|
|
1131
|
-
return this.builder.explain(instructionName, [instructionGetter]);
|
|
1132
|
-
}
|
|
1133
|
-
/**
|
|
1134
|
-
* Debug analyze without executing
|
|
1135
|
-
*/
|
|
1136
|
-
async analyze(instructionName, instructionGetter) {
|
|
1137
|
-
return this.builder.debug(instructionName, [instructionGetter]);
|
|
1138
|
-
}
|
|
1139
|
-
/**
|
|
1140
|
-
* Get decoded account
|
|
1141
|
-
*/
|
|
1142
|
-
async getAccount(address2, decoderImportName) {
|
|
1143
|
-
return this.builder.getAccount(address2, decoderImportName);
|
|
1144
|
-
}
|
|
1145
|
-
/**
|
|
1146
|
-
* Get multiple decoded accounts
|
|
1147
|
-
*/
|
|
1148
|
-
async getAccounts(addresses, decoderImportName) {
|
|
1149
|
-
return this.builder.getAccounts(addresses, decoderImportName);
|
|
1150
|
-
}
|
|
1151
|
-
/**
|
|
1152
|
-
* Get program accounts
|
|
1153
|
-
*/
|
|
1154
|
-
async getProgramAccounts(decoderImportName, filters) {
|
|
1155
|
-
return this.builder.getProgramAccounts(decoderImportName, filters);
|
|
1156
|
-
}
|
|
1157
|
-
/**
|
|
1158
|
-
* Get program ID
|
|
1159
|
-
*/
|
|
1160
|
-
get programId() {
|
|
1161
|
-
return this.config.programId;
|
|
1162
|
-
}
|
|
1163
|
-
/**
|
|
1164
|
-
* Get program ID (public accessor)
|
|
1165
|
-
*/
|
|
1166
|
-
getProgramId() {
|
|
1167
|
-
return this.config.programId;
|
|
1168
|
-
}
|
|
1169
|
-
/**
|
|
1170
|
-
* Get commitment level
|
|
1171
|
-
*/
|
|
1172
|
-
get commitment() {
|
|
1173
|
-
return this.config.commitment ?? "confirmed";
|
|
1174
|
-
}
|
|
1175
|
-
/**
|
|
1176
|
-
* Get commitment level (public accessor)
|
|
1177
|
-
*/
|
|
1178
|
-
getCommitment() {
|
|
1179
|
-
return this.config.commitment ?? "confirmed";
|
|
1180
|
-
}
|
|
1181
|
-
};
|
|
1182
|
-
|
|
1183
|
-
// src/utils/ipfs-utils.ts
|
|
1184
|
-
var DEFAULT_IPFS_CONFIG = {
|
|
1185
|
-
provider: {
|
|
1186
|
-
name: "pinata",
|
|
1187
|
-
endpoint: "https://api.pinata.cloud"
|
|
1188
|
-
},
|
|
1189
|
-
gateways: [
|
|
1190
|
-
"https://gateway.pinata.cloud",
|
|
1191
|
-
"https://ipfs.io",
|
|
1192
|
-
"https://cloudflare-ipfs.com",
|
|
1193
|
-
"https://gateway.ipfs.io"
|
|
1194
|
-
],
|
|
1195
|
-
autoPinning: true,
|
|
1196
|
-
sizeThreshold: 800,
|
|
1197
|
-
// 800 bytes threshold to stay under Solana transaction limits
|
|
1198
|
-
maxRetries: 3,
|
|
1199
|
-
retryDelay: 1e3,
|
|
1200
|
-
enableCache: true,
|
|
1201
|
-
cacheTTL: 3e5
|
|
1202
|
-
// 5 minutes
|
|
1203
|
-
};
|
|
1204
|
-
var IPFSUtils = class {
|
|
1205
|
-
client;
|
|
1206
|
-
constructor(config) {
|
|
1207
|
-
this.client = new IPFSClient(config);
|
|
1208
|
-
}
|
|
1209
|
-
/**
|
|
1210
|
-
* Store agent metadata with automatic IPFS/inline decision
|
|
1211
|
-
*/
|
|
1212
|
-
async storeAgentMetadata(metadata, options) {
|
|
1213
|
-
const metadataJson = JSON.stringify({
|
|
1214
|
-
...metadata,
|
|
1215
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1216
|
-
version: "1.0.0"
|
|
1217
|
-
});
|
|
1218
|
-
return this.client.storeContent(metadataJson, "agent-metadata", {
|
|
1219
|
-
filename: `agent-${metadata.agentId ?? "metadata"}.json`,
|
|
1220
|
-
metadata: {
|
|
1221
|
-
type: "agent-metadata",
|
|
1222
|
-
agentId: metadata.agentId,
|
|
1223
|
-
name: metadata.name
|
|
1224
|
-
},
|
|
1225
|
-
contentType: "application/json",
|
|
1226
|
-
...options
|
|
1227
|
-
});
|
|
1228
|
-
}
|
|
1229
|
-
/**
|
|
1230
|
-
* Store channel message content with automatic IPFS/inline decision
|
|
1231
|
-
*/
|
|
1232
|
-
async storeChannelMessage(message, options) {
|
|
1233
|
-
const messageJson = JSON.stringify({
|
|
1234
|
-
...message,
|
|
1235
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1236
|
-
version: "1.0.0"
|
|
1237
|
-
});
|
|
1238
|
-
return this.client.storeContent(messageJson, "channel-message", {
|
|
1239
|
-
filename: `message-${Date.now()}.json`,
|
|
1240
|
-
metadata: {
|
|
1241
|
-
type: "channel-message",
|
|
1242
|
-
channelId: message.channelId,
|
|
1243
|
-
messageType: message.messageType ?? 0
|
|
1244
|
-
},
|
|
1245
|
-
contentType: "application/json",
|
|
1246
|
-
...options
|
|
1247
|
-
});
|
|
1248
|
-
}
|
|
1249
|
-
/**
|
|
1250
|
-
* Store file attachments on IPFS
|
|
1251
|
-
*/
|
|
1252
|
-
async storeFileAttachment(fileContent, filename, contentType, options) {
|
|
1253
|
-
const content = typeof fileContent === "string" ? fileContent : new TextDecoder().decode(fileContent);
|
|
1254
|
-
return this.client.storeContent(content, "file-attachment", {
|
|
1255
|
-
filename,
|
|
1256
|
-
contentType,
|
|
1257
|
-
metadata: {
|
|
1258
|
-
type: "file-attachment",
|
|
1259
|
-
originalFilename: filename,
|
|
1260
|
-
mimeType: contentType
|
|
1261
|
-
},
|
|
1262
|
-
...options
|
|
1263
|
-
});
|
|
1264
|
-
}
|
|
1265
|
-
/**
|
|
1266
|
-
* Retrieve and parse agent metadata
|
|
1267
|
-
*/
|
|
1268
|
-
async retrieveAgentMetadata(uri) {
|
|
1269
|
-
const content = await this.client.retrieveContent(uri);
|
|
1270
|
-
const parsed = JSON.parse(content);
|
|
1271
|
-
if (typeof parsed !== "object" || parsed === null) {
|
|
1272
|
-
throw new Error("Retrieved agent metadata is not a valid object");
|
|
1273
|
-
}
|
|
1274
|
-
return parsed;
|
|
1275
|
-
}
|
|
1276
|
-
/**
|
|
1277
|
-
* Retrieve and parse channel message content
|
|
1278
|
-
*/
|
|
1279
|
-
async retrieveChannelMessage(uri) {
|
|
1280
|
-
const content = await this.client.retrieveContent(uri);
|
|
1281
|
-
const parsed = JSON.parse(content);
|
|
1282
|
-
if (typeof parsed !== "object" || parsed === null) {
|
|
1283
|
-
throw new Error("Retrieved channel message is not a valid object");
|
|
1284
|
-
}
|
|
1285
|
-
return parsed;
|
|
1286
|
-
}
|
|
1287
|
-
/**
|
|
1288
|
-
* Batch upload multiple content items
|
|
1289
|
-
*/
|
|
1290
|
-
async batchUpload(items) {
|
|
1291
|
-
const results = await Promise.allSettled(
|
|
1292
|
-
items.map(
|
|
1293
|
-
(item) => this.client.storeContent(item.content, item.type, {
|
|
1294
|
-
filename: item.filename,
|
|
1295
|
-
...item.options
|
|
1296
|
-
})
|
|
1297
|
-
)
|
|
1298
|
-
);
|
|
1299
|
-
return results.map((result) => {
|
|
1300
|
-
if (result.status === "fulfilled") {
|
|
1301
|
-
return {
|
|
1302
|
-
success: true,
|
|
1303
|
-
data: result.value
|
|
1304
|
-
};
|
|
1305
|
-
} else {
|
|
1306
|
-
return {
|
|
1307
|
-
success: false,
|
|
1308
|
-
error: "UPLOAD_FAILED",
|
|
1309
|
-
message: result.reason instanceof Error ? result.reason.message : String(result.reason)
|
|
1310
|
-
};
|
|
1311
|
-
}
|
|
1312
|
-
});
|
|
1313
|
-
}
|
|
1314
|
-
/**
|
|
1315
|
-
* Pin existing content by hash
|
|
1316
|
-
*/
|
|
1317
|
-
async pinContent(hash) {
|
|
1318
|
-
const result = await this.client.pin(hash);
|
|
1319
|
-
return {
|
|
1320
|
-
...result,
|
|
1321
|
-
data: result.success
|
|
1322
|
-
};
|
|
1323
|
-
}
|
|
1324
|
-
/**
|
|
1325
|
-
* Check if a URI uses IPFS storage
|
|
1326
|
-
*/
|
|
1327
|
-
isIPFSUri(uri) {
|
|
1328
|
-
return uri.startsWith("ipfs://");
|
|
1329
|
-
}
|
|
1330
|
-
/**
|
|
1331
|
-
* Extract IPFS hash from URI
|
|
1332
|
-
*/
|
|
1333
|
-
extractIPFSHash(uri) {
|
|
1334
|
-
if (!this.isIPFSUri(uri)) {
|
|
1335
|
-
return null;
|
|
1336
|
-
}
|
|
1337
|
-
return uri.replace("ipfs://", "");
|
|
1338
|
-
}
|
|
1339
|
-
/**
|
|
1340
|
-
* Convert IPFS hash to gateway URLs
|
|
1341
|
-
*/
|
|
1342
|
-
getGatewayUrls(hash, gateways) {
|
|
1343
|
-
const defaultGateways = gateways ?? DEFAULT_IPFS_CONFIG.gateways ?? [];
|
|
1344
|
-
return defaultGateways.map((gateway) => `${gateway}/ipfs/${hash}`);
|
|
1345
|
-
}
|
|
1346
|
-
/**
|
|
1347
|
-
* Validate IPFS hash format
|
|
1348
|
-
*/
|
|
1349
|
-
isValidIPFSHash(hash) {
|
|
1350
|
-
if (hash.length < 44) return false;
|
|
1351
|
-
if (hash.startsWith("Qm") && hash.length === 46) {
|
|
1352
|
-
return /^Qm[A-Za-z0-9]{44}$/.test(hash);
|
|
1353
|
-
}
|
|
1354
|
-
if (hash.length > 46) {
|
|
1355
|
-
return /^[A-Za-z0-9]+$/.test(hash);
|
|
1356
|
-
}
|
|
1357
|
-
return false;
|
|
1358
|
-
}
|
|
1359
|
-
/**
|
|
1360
|
-
* Calculate content size to determine if IPFS should be used
|
|
1361
|
-
*/
|
|
1362
|
-
shouldUseIPFS(content, threshold) {
|
|
1363
|
-
const size = new TextEncoder().encode(content).length;
|
|
1364
|
-
const sizeThreshold = threshold ?? DEFAULT_IPFS_CONFIG.sizeThreshold ?? 800;
|
|
1365
|
-
return size > sizeThreshold;
|
|
1366
|
-
}
|
|
1367
|
-
/**
|
|
1368
|
-
* Compress content before IPFS upload using modern compression APIs
|
|
1369
|
-
*/
|
|
1370
|
-
async compressContent(content) {
|
|
1371
|
-
try {
|
|
1372
|
-
if (typeof CompressionStream !== "undefined") {
|
|
1373
|
-
const compressedStream = new CompressionStream("gzip");
|
|
1374
|
-
const writer = compressedStream.writable.getWriter();
|
|
1375
|
-
const reader = compressedStream.readable.getReader();
|
|
1376
|
-
const encoder = new TextEncoder();
|
|
1377
|
-
const input = encoder.encode(content);
|
|
1378
|
-
const writePromise = writer.write(input).then(() => writer.close());
|
|
1379
|
-
const chunks = [];
|
|
1380
|
-
const readCompressed = async () => {
|
|
1381
|
-
const result = await reader.read();
|
|
1382
|
-
const { done, value } = result;
|
|
1383
|
-
if (!done && value) {
|
|
1384
|
-
chunks.push(value);
|
|
1385
|
-
await readCompressed();
|
|
1386
|
-
}
|
|
1387
|
-
};
|
|
1388
|
-
await Promise.all([writePromise, readCompressed()]);
|
|
1389
|
-
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
1390
|
-
const compressedData = new Uint8Array(totalLength);
|
|
1391
|
-
let offset = 0;
|
|
1392
|
-
for (const chunk of chunks) {
|
|
1393
|
-
compressedData.set(chunk, offset);
|
|
1394
|
-
offset += chunk.length;
|
|
1395
|
-
}
|
|
1396
|
-
const compressed = Buffer.from(compressedData).toString("base64");
|
|
1397
|
-
return {
|
|
1398
|
-
compressed,
|
|
1399
|
-
algorithm: "gzip"
|
|
1400
|
-
};
|
|
1401
|
-
} else {
|
|
1402
|
-
console.warn("Compression not available in this environment, storing uncompressed");
|
|
1403
|
-
return {
|
|
1404
|
-
compressed: content,
|
|
1405
|
-
algorithm: "none"
|
|
1406
|
-
};
|
|
1407
|
-
}
|
|
1408
|
-
} catch (error) {
|
|
1409
|
-
console.warn("Compression failed, falling back to uncompressed:", error);
|
|
1410
|
-
return {
|
|
1411
|
-
compressed: content,
|
|
1412
|
-
algorithm: "none"
|
|
1413
|
-
};
|
|
1414
|
-
}
|
|
1415
|
-
}
|
|
1416
|
-
/**
|
|
1417
|
-
* Decompress content after IPFS retrieval using modern decompression APIs
|
|
1418
|
-
*/
|
|
1419
|
-
async decompressContent(compressed, algorithm) {
|
|
1420
|
-
if (algorithm === "none") {
|
|
1421
|
-
return compressed;
|
|
1422
|
-
}
|
|
1423
|
-
try {
|
|
1424
|
-
if (algorithm === "gzip") {
|
|
1425
|
-
if (typeof DecompressionStream !== "undefined") {
|
|
1426
|
-
const decompressedStream = new DecompressionStream("gzip");
|
|
1427
|
-
const writer = decompressedStream.writable.getWriter();
|
|
1428
|
-
const reader = decompressedStream.readable.getReader();
|
|
1429
|
-
const compressedData = Buffer.from(compressed, "base64");
|
|
1430
|
-
const writePromise = writer.write(compressedData).then(() => writer.close());
|
|
1431
|
-
const chunks = [];
|
|
1432
|
-
const readDecompressed = async () => {
|
|
1433
|
-
const result = await reader.read();
|
|
1434
|
-
const { done, value } = result;
|
|
1435
|
-
if (!done && value) {
|
|
1436
|
-
chunks.push(value);
|
|
1437
|
-
await readDecompressed();
|
|
1438
|
-
}
|
|
1439
|
-
};
|
|
1440
|
-
await Promise.all([writePromise, readDecompressed()]);
|
|
1441
|
-
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
1442
|
-
const decompressedData = new Uint8Array(totalLength);
|
|
1443
|
-
let offset = 0;
|
|
1444
|
-
for (const chunk of chunks) {
|
|
1445
|
-
decompressedData.set(chunk, offset);
|
|
1446
|
-
offset += chunk.length;
|
|
1447
|
-
}
|
|
1448
|
-
const decoder = new TextDecoder();
|
|
1449
|
-
return decoder.decode(decompressedData);
|
|
1450
|
-
} else {
|
|
1451
|
-
console.warn("Decompression not available in this environment, returning compressed data");
|
|
1452
|
-
return compressed;
|
|
1453
|
-
}
|
|
1454
|
-
} else {
|
|
1455
|
-
console.warn(`Unknown compression algorithm: ${algorithm}`);
|
|
1456
|
-
return compressed;
|
|
1457
|
-
}
|
|
1458
|
-
} catch (error) {
|
|
1459
|
-
console.error("Decompression failed, returning compressed data:", error);
|
|
1460
|
-
return compressed;
|
|
1461
|
-
}
|
|
1462
|
-
}
|
|
1463
|
-
/**
|
|
1464
|
-
* Get client stats
|
|
1465
|
-
*/
|
|
1466
|
-
getStats() {
|
|
1467
|
-
return {
|
|
1468
|
-
cacheStats: this.client.getCacheStats(),
|
|
1469
|
-
config: DEFAULT_IPFS_CONFIG
|
|
1470
|
-
};
|
|
1471
|
-
}
|
|
1472
|
-
/**
|
|
1473
|
-
* Clear client cache
|
|
1474
|
-
*/
|
|
1475
|
-
clearCache() {
|
|
1476
|
-
this.client.clearCache();
|
|
1477
|
-
}
|
|
1478
|
-
};
|
|
1479
|
-
function createIPFSUtils(config) {
|
|
1480
|
-
const finalConfig = {
|
|
1481
|
-
...DEFAULT_IPFS_CONFIG,
|
|
1482
|
-
...config,
|
|
1483
|
-
provider: {
|
|
1484
|
-
...DEFAULT_IPFS_CONFIG.provider,
|
|
1485
|
-
...config?.provider
|
|
1486
|
-
}
|
|
1487
|
-
};
|
|
1488
|
-
return new IPFSUtils(finalConfig);
|
|
1489
|
-
}
|
|
1490
|
-
function determineStorageMethod(content, options) {
|
|
1491
|
-
if (options?.forceInline) return "inline";
|
|
1492
|
-
if (options?.forceIPFS) return "ipfs";
|
|
1493
|
-
const size = new TextEncoder().encode(content).length;
|
|
1494
|
-
const threshold = options?.sizeThreshold ?? DEFAULT_IPFS_CONFIG.sizeThreshold ?? 800;
|
|
1495
|
-
return size > threshold ? "ipfs" : "inline";
|
|
1496
|
-
}
|
|
1497
|
-
async function createMetadataUri(metadata, ipfsUtils, options) {
|
|
1498
|
-
const metadataJson = JSON.stringify(metadata);
|
|
1499
|
-
const storageMethod = determineStorageMethod(metadataJson, {
|
|
1500
|
-
forceIPFS: options?.forceIPFS
|
|
1501
|
-
});
|
|
1502
|
-
if (storageMethod === "inline" || !ipfsUtils) {
|
|
1503
|
-
const encoded = Buffer.from(metadataJson).toString("base64");
|
|
1504
|
-
return `data:application/json;base64,${encoded}`;
|
|
1505
|
-
} else {
|
|
1506
|
-
const result = await ipfsUtils.client.storeContent(
|
|
1507
|
-
metadataJson,
|
|
1508
|
-
options?.type ?? "custom",
|
|
1509
|
-
{
|
|
1510
|
-
filename: options?.filename,
|
|
1511
|
-
contentType: "application/json"
|
|
1512
|
-
}
|
|
1513
|
-
);
|
|
1514
|
-
return result.uri;
|
|
1515
|
-
}
|
|
1516
|
-
}
|
|
1517
|
-
|
|
1518
|
-
// src/core/modules/AgentModule.ts
|
|
1519
|
-
var AgentModule = class extends BaseModule {
|
|
1520
|
-
ipfsUtils = null;
|
|
1521
|
-
constructor(config) {
|
|
1522
|
-
super(config);
|
|
1523
|
-
if (config.ipfsConfig) {
|
|
1524
|
-
this.ipfsUtils = createIPFSUtils(config.ipfsConfig);
|
|
1525
|
-
}
|
|
1526
|
-
}
|
|
1527
|
-
/**
|
|
1528
|
-
* Register a new agent
|
|
1529
|
-
*/
|
|
1530
|
-
async register(signer, params) {
|
|
1531
|
-
const registerGetter = async () => {
|
|
1532
|
-
const agentAccount = await this.deriveAgentPda(params.agentId, signer.address);
|
|
1533
|
-
const ix = await getRegisterAgentInstructionAsync({
|
|
1534
|
-
agentAccount,
|
|
1535
|
-
signer,
|
|
1536
|
-
systemProgram: this.systemProgramId,
|
|
1537
|
-
agentType: params.agentType,
|
|
1538
|
-
name: params.name,
|
|
1539
|
-
description: params.description,
|
|
1540
|
-
metadataUri: params.metadataUri,
|
|
1541
|
-
agentId: params.agentId
|
|
1542
|
-
});
|
|
1543
|
-
return ix;
|
|
1544
|
-
};
|
|
1545
|
-
const heapGetter = () => {
|
|
1546
|
-
const heapData = new Uint8Array(5);
|
|
1547
|
-
heapData[0] = 1;
|
|
1548
|
-
new DataView(heapData.buffer).setUint32(1, 256 * 1024, true);
|
|
1549
|
-
return {
|
|
1550
|
-
programAddress: "ComputeBudget111111111111111111111111111111",
|
|
1551
|
-
accounts: [],
|
|
1552
|
-
data: heapData
|
|
1553
|
-
};
|
|
1554
|
-
};
|
|
1555
|
-
this.debug();
|
|
1556
|
-
if (params.skipSimulation) {
|
|
1557
|
-
console.log("\u{1F680} SKIPPING SIMULATION - Sending transaction directly");
|
|
1558
|
-
return this.builder.executeBatch(
|
|
1559
|
-
"registerAgent",
|
|
1560
|
-
[heapGetter, registerGetter],
|
|
1561
|
-
[signer],
|
|
1562
|
-
{ simulate: false, skipPreflight: true }
|
|
1563
|
-
);
|
|
1564
|
-
}
|
|
1565
|
-
return this.builder.executeBatch(
|
|
1566
|
-
"registerAgent",
|
|
1567
|
-
[heapGetter, registerGetter],
|
|
1568
|
-
[signer]
|
|
1569
|
-
);
|
|
1570
|
-
}
|
|
1571
|
-
/**
|
|
1572
|
-
* Register a compressed agent (5000x cheaper)
|
|
1573
|
-
*/
|
|
1574
|
-
async registerCompressed(signer, params) {
|
|
1575
|
-
const instructionGetter = async () => {
|
|
1576
|
-
const treeConfig = params.treeConfig || await this.deriveTreeConfigPda(signer.address);
|
|
1577
|
-
const result = await getRegisterAgentCompressedInstructionAsync({
|
|
1578
|
-
merkleTree: params.merkleTree,
|
|
1579
|
-
treeAuthority: treeConfig,
|
|
1580
|
-
// Map to correct instruction field (it's treeAuthority in IDL?)
|
|
1581
|
-
signer,
|
|
1582
|
-
systemProgram: this.systemProgramId,
|
|
1583
|
-
compressionProgram: this.compressionProgramId,
|
|
1584
|
-
agentType: params.agentType,
|
|
1585
|
-
name: params.name,
|
|
1586
|
-
description: params.description,
|
|
1587
|
-
metadataUri: params.metadataUri,
|
|
1588
|
-
agentId: params.agentId,
|
|
1589
|
-
logWrapper: "noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV"
|
|
1590
|
-
// Explicitly provide Noop program
|
|
1591
|
-
});
|
|
1592
|
-
return result;
|
|
1593
|
-
};
|
|
1594
|
-
return this.execute(
|
|
1595
|
-
"registerAgentCompressed",
|
|
1596
|
-
instructionGetter,
|
|
1597
|
-
[signer]
|
|
1598
|
-
);
|
|
1599
|
-
}
|
|
1600
|
-
/**
|
|
1601
|
-
* Update agent metadata
|
|
1602
|
-
*/
|
|
1603
|
-
async update(signer, params) {
|
|
1604
|
-
const instructionGetter = () => {
|
|
1605
|
-
const result = getUpdateAgentInstruction({
|
|
1606
|
-
agentAccount: params.agentAddress,
|
|
1607
|
-
signer,
|
|
1608
|
-
metadataUri: params.metadataUri,
|
|
1609
|
-
agentType: params.agentType,
|
|
1610
|
-
agentId: params.agentId,
|
|
1611
|
-
name: params.name ?? null,
|
|
1612
|
-
description: params.description ?? null
|
|
1613
|
-
});
|
|
1614
|
-
return result;
|
|
1615
|
-
};
|
|
1616
|
-
return this.execute(
|
|
1617
|
-
"updateAgent",
|
|
1618
|
-
instructionGetter,
|
|
1619
|
-
[signer]
|
|
1620
|
-
);
|
|
1621
|
-
}
|
|
1622
|
-
/**
|
|
1623
|
-
* Verify an agent
|
|
1624
|
-
*/
|
|
1625
|
-
async verify(signer, params) {
|
|
1626
|
-
const instructionGetter = async () => {
|
|
1627
|
-
const result = await getVerifyAgentInstructionAsync({
|
|
1628
|
-
agent: params.agentAddress,
|
|
1629
|
-
verifier: signer,
|
|
1630
|
-
agentPubkey: params.agentPubkey,
|
|
1631
|
-
serviceEndpoint: params.serviceEndpoint,
|
|
1632
|
-
supportedCapabilities: params.supportedCapabilities,
|
|
1633
|
-
verifiedAt: params.verifiedAt
|
|
1634
|
-
});
|
|
1635
|
-
return result;
|
|
1636
|
-
};
|
|
1637
|
-
return this.execute(
|
|
1638
|
-
"verifyAgent",
|
|
1639
|
-
instructionGetter,
|
|
1640
|
-
[signer]
|
|
1641
|
-
);
|
|
1642
|
-
}
|
|
1643
|
-
/**
|
|
1644
|
-
* Deactivate an agent
|
|
1645
|
-
*/
|
|
1646
|
-
async deactivate(signer, params) {
|
|
1647
|
-
const instructionGetter = () => {
|
|
1648
|
-
const result = getDeactivateAgentInstruction({
|
|
1649
|
-
agentAccount: params.agentAddress,
|
|
1650
|
-
signer,
|
|
1651
|
-
agentId: params.agentId
|
|
1652
|
-
});
|
|
1653
|
-
return result;
|
|
1654
|
-
};
|
|
1655
|
-
return this.execute(
|
|
1656
|
-
"deactivateAgent",
|
|
1657
|
-
instructionGetter,
|
|
1658
|
-
[signer]
|
|
1659
|
-
);
|
|
1660
|
-
}
|
|
1661
|
-
/**
|
|
1662
|
-
* Activate an agent
|
|
1663
|
-
*/
|
|
1664
|
-
async activate(signer, params) {
|
|
1665
|
-
const instructionGetter = () => {
|
|
1666
|
-
const result = getActivateAgentInstruction({
|
|
1667
|
-
agentAccount: params.agentAddress,
|
|
1668
|
-
signer,
|
|
1669
|
-
agentId: params.agentId
|
|
1670
|
-
});
|
|
1671
|
-
return result;
|
|
1672
|
-
};
|
|
1673
|
-
return this.execute(
|
|
1674
|
-
"activateAgent",
|
|
1675
|
-
instructionGetter,
|
|
1676
|
-
[signer]
|
|
1677
|
-
);
|
|
1678
|
-
}
|
|
1679
|
-
/**
|
|
1680
|
-
* Get agent account
|
|
1681
|
-
*/
|
|
1682
|
-
async getAgentAccount(address2) {
|
|
1683
|
-
return super.getAccount(address2, "getAgentDecoder");
|
|
1684
|
-
}
|
|
1685
|
-
/**
|
|
1686
|
-
* Get all agents
|
|
1687
|
-
*/
|
|
1688
|
-
async getAllAgents() {
|
|
1689
|
-
return this.getProgramAccounts("getAgentDecoder");
|
|
1690
|
-
}
|
|
1691
|
-
/**
|
|
1692
|
-
* Get agents by type
|
|
1693
|
-
*/
|
|
1694
|
-
async getAgentsByType(agentType) {
|
|
1695
|
-
const typeBytes = Buffer.alloc(1);
|
|
1696
|
-
typeBytes.writeUInt8(agentType, 0);
|
|
1697
|
-
const filters = [{
|
|
1698
|
-
memcmp: {
|
|
1699
|
-
offset: BigInt(8),
|
|
1700
|
-
// Skip discriminator
|
|
1701
|
-
bytes: typeBytes.toString("base64"),
|
|
1702
|
-
encoding: "base64"
|
|
1703
|
-
}
|
|
1704
|
-
}];
|
|
1705
|
-
return this.getProgramAccounts("getAgentDecoder", filters);
|
|
1706
|
-
}
|
|
1707
|
-
/**
|
|
1708
|
-
* Get user's agents
|
|
1709
|
-
*/
|
|
1710
|
-
async getUserAgents(authority) {
|
|
1711
|
-
const filters = [{
|
|
1712
|
-
memcmp: {
|
|
1713
|
-
offset: BigInt(9),
|
|
1714
|
-
// Skip discriminator + type
|
|
1715
|
-
bytes: authority,
|
|
1716
|
-
encoding: "base58"
|
|
1717
|
-
}
|
|
1718
|
-
}];
|
|
1719
|
-
return this.getProgramAccounts("getAgentDecoder", filters);
|
|
1720
|
-
}
|
|
1721
|
-
// Helper methods
|
|
1722
|
-
async deriveAgentPda(agentId, owner) {
|
|
1723
|
-
const { deriveAgentPdaOriginal } = await import('./pda-S4BFJVGE.js');
|
|
1724
|
-
return deriveAgentPdaOriginal(this.programId, owner, agentId);
|
|
1725
|
-
}
|
|
1726
|
-
async deriveUserRegistryPda(owner) {
|
|
1727
|
-
const { deriveUserRegistryPda } = await import('./pda-S4BFJVGE.js');
|
|
1728
|
-
return deriveUserRegistryPda(this.programId, owner);
|
|
1729
|
-
}
|
|
1730
|
-
async deriveTreeConfigPda(owner) {
|
|
1731
|
-
const { getProgramDerivedAddress: getProgramDerivedAddress2, getAddressEncoder: getAddressEncoder2 } = await import('@solana/addresses');
|
|
1732
|
-
const addressEncoder = getAddressEncoder2();
|
|
1733
|
-
const ownerBytes = addressEncoder.encode(owner);
|
|
1734
|
-
const [pda] = await getProgramDerivedAddress2({
|
|
1735
|
-
programAddress: this.programId,
|
|
1736
|
-
seeds: [
|
|
1737
|
-
new TextEncoder().encode("agent_tree_config"),
|
|
1738
|
-
ownerBytes
|
|
1739
|
-
]
|
|
1740
|
-
});
|
|
1741
|
-
return pda;
|
|
1742
|
-
}
|
|
1743
|
-
get systemProgramId() {
|
|
1744
|
-
return SYSTEM_PROGRAM_ADDRESS;
|
|
1745
|
-
}
|
|
1746
|
-
get compressionProgramId() {
|
|
1747
|
-
return "cmtDvXumGCrqC1Age74AVPhSRVXJMd8PJS91L8KbNCK";
|
|
1748
|
-
}
|
|
1749
|
-
};
|
|
1750
|
-
var GHOSTSPEAK_PROGRAM_ID = address("GpvFxus2eecFKcqa2bhxXeRjpstPeCEJNX216TQCcNC9");
|
|
1751
|
-
var NETWORK_CONFIG = {
|
|
1752
|
-
devnet: {
|
|
1753
|
-
programId: "GpvFxus2eecFKcqa2bhxXeRjpstPeCEJNX216TQCcNC9",
|
|
1754
|
-
rpcUrl: "https://api.devnet.solana.com"
|
|
1755
|
-
},
|
|
1756
|
-
testnet: {
|
|
1757
|
-
programId: "GpvFxus2eecFKcqa2bhxXeRjpstPeCEJNX216TQCcNC9",
|
|
1758
|
-
rpcUrl: "https://api.testnet.solana.com"
|
|
1759
|
-
},
|
|
1760
|
-
mainnet: {
|
|
1761
|
-
programId: "GpvFxus2eecFKcqa2bhxXeRjpstPeCEJNX216TQCcNC9",
|
|
1762
|
-
rpcUrl: "https://api.mainnet-beta.solana.com"
|
|
1763
|
-
}
|
|
1764
|
-
};
|
|
1765
|
-
var TOKEN_PROGRAM_ADDRESS = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
|
|
1766
|
-
var NATIVE_SOL_MINT = "So11111111111111111111111111111111111111112";
|
|
1767
|
-
async function deriveEscrowPdaFromTaskId(programId, taskId) {
|
|
1768
|
-
const encoder = new TextEncoder();
|
|
1769
|
-
const [pda] = await getProgramDerivedAddress({
|
|
1770
|
-
programAddress: programId,
|
|
1771
|
-
seeds: [
|
|
1772
|
-
new Uint8Array([101, 115, 99, 114, 111, 119]),
|
|
1773
|
-
// "escrow"
|
|
1774
|
-
encoder.encode(taskId)
|
|
1775
|
-
]
|
|
1776
|
-
});
|
|
1777
|
-
return pda;
|
|
1778
|
-
}
|
|
1779
|
-
async function deriveReentrancyGuardPda(programId) {
|
|
1780
|
-
const [pda] = await getProgramDerivedAddress({
|
|
1781
|
-
programAddress: programId,
|
|
1782
|
-
seeds: [
|
|
1783
|
-
new Uint8Array([114, 101, 101, 110, 116, 114, 97, 110, 99, 121, 95, 103, 117, 97, 114, 100])
|
|
1784
|
-
// "reentrancy_guard"
|
|
1785
|
-
]
|
|
1786
|
-
});
|
|
1787
|
-
return pda;
|
|
1788
|
-
}
|
|
1789
|
-
async function deriveToken2022ATA(wallet, mint) {
|
|
1790
|
-
const [ata] = await getProgramDerivedAddress({
|
|
1791
|
-
programAddress: ASSOCIATED_TOKEN_PROGRAM_ADDRESS,
|
|
1792
|
-
seeds: [
|
|
1793
|
-
getAddressEncoder().encode(wallet),
|
|
1794
|
-
getAddressEncoder().encode(TOKEN_2022_PROGRAM_ADDRESS),
|
|
1795
|
-
getAddressEncoder().encode(mint)
|
|
1796
|
-
]
|
|
1797
|
-
});
|
|
1798
|
-
return ata;
|
|
1799
|
-
}
|
|
1800
|
-
async function deriveTokenATA(wallet, mint) {
|
|
1801
|
-
const [ata] = await getProgramDerivedAddress({
|
|
1802
|
-
programAddress: ASSOCIATED_TOKEN_PROGRAM_ADDRESS,
|
|
1803
|
-
seeds: [
|
|
1804
|
-
getAddressEncoder().encode(wallet),
|
|
1805
|
-
getAddressEncoder().encode(TOKEN_PROGRAM_ADDRESS),
|
|
1806
|
-
getAddressEncoder().encode(mint)
|
|
1807
|
-
]
|
|
1808
|
-
});
|
|
1809
|
-
return ata;
|
|
1810
|
-
}
|
|
1811
|
-
var EscrowModule = class extends BaseModule {
|
|
1812
|
-
/**
|
|
1813
|
-
* Create a new escrow
|
|
1814
|
-
* @param params.paymentToken - The Token2022 mint to use (defaults to Token2022 native wSOL)
|
|
1815
|
-
*/
|
|
1816
|
-
async create(params) {
|
|
1817
|
-
const taskId = params.description;
|
|
1818
|
-
const paymentToken = params.paymentToken ?? this.defaultPaymentToken;
|
|
1819
|
-
const expiresAt = BigInt(Math.floor(Date.now() / 1e3) + (params.expiresInDays ?? 30) * 24 * 60 * 60);
|
|
1820
|
-
const escrowAddress = await deriveEscrowPdaFromTaskId(GHOSTSPEAK_PROGRAM_ID, taskId);
|
|
1821
|
-
const clientTokenAccount = await deriveToken2022ATA(params.signer.address, paymentToken);
|
|
1822
|
-
const escrowTokenAccount = await deriveToken2022ATA(escrowAddress, paymentToken);
|
|
1823
|
-
return this.execute(
|
|
1824
|
-
"createEscrow",
|
|
1825
|
-
() => getCreateEscrowInstructionAsync({
|
|
1826
|
-
escrow: escrowAddress,
|
|
1827
|
-
// reentrancyGuard auto-derived by generated instruction
|
|
1828
|
-
client: params.signer,
|
|
1829
|
-
agent: params.seller,
|
|
1830
|
-
paymentToken,
|
|
1831
|
-
clientTokenAccount,
|
|
1832
|
-
escrowTokenAccount,
|
|
1833
|
-
taskId,
|
|
1834
|
-
amount: params.amount,
|
|
1835
|
-
expiresAt,
|
|
1836
|
-
transferHook: null,
|
|
1837
|
-
isConfidential: false
|
|
1838
|
-
}),
|
|
1839
|
-
[params.signer]
|
|
1840
|
-
);
|
|
1841
|
-
}
|
|
1842
|
-
/**
|
|
1843
|
-
* Create an escrow with native SOL (auto-wraps to wSOL)
|
|
1844
|
-
* This is the easiest way to create an escrow - just send SOL!
|
|
1845
|
-
*/
|
|
1846
|
-
async createWithSol(params) {
|
|
1847
|
-
const taskId = params.description;
|
|
1848
|
-
const expiresAt = BigInt(Math.floor(Date.now() / 1e3) + (params.expiresInDays ?? 30) * 24 * 60 * 60);
|
|
1849
|
-
const escrowAddress = await deriveEscrowPdaFromTaskId(GHOSTSPEAK_PROGRAM_ID, taskId);
|
|
1850
|
-
const clientWsolAccount = await deriveTokenATA(params.signer.address, NATIVE_SOL_MINT);
|
|
1851
|
-
const escrowWsolAccount = await deriveTokenATA(escrowAddress, NATIVE_SOL_MINT);
|
|
1852
|
-
return this.execute(
|
|
1853
|
-
"createEscrowWithSol",
|
|
1854
|
-
() => getCreateEscrowWithSolInstructionAsync({
|
|
1855
|
-
escrow: escrowAddress,
|
|
1856
|
-
client: params.signer,
|
|
1857
|
-
agent: params.seller,
|
|
1858
|
-
clientWsolAccount,
|
|
1859
|
-
escrowWsolAccount,
|
|
1860
|
-
taskId,
|
|
1861
|
-
amount: params.amount,
|
|
1862
|
-
expiresAt,
|
|
1863
|
-
transferHook: null,
|
|
1864
|
-
isConfidential: false
|
|
1865
|
-
}),
|
|
1866
|
-
[params.signer]
|
|
1867
|
-
);
|
|
1868
|
-
}
|
|
1869
|
-
/**
|
|
1870
|
-
* Complete an escrow - releases funds to the agent
|
|
1871
|
-
* @param taskId - The original task description used to derive the escrow PDA
|
|
1872
|
-
*/
|
|
1873
|
-
async complete(signer, taskId, paymentToken) {
|
|
1874
|
-
const mint = paymentToken ?? this.defaultPaymentToken;
|
|
1875
|
-
const escrowAddress = await deriveEscrowPdaFromTaskId(GHOSTSPEAK_PROGRAM_ID, taskId);
|
|
1876
|
-
const reentrancyGuard = await deriveReentrancyGuardPda(GHOSTSPEAK_PROGRAM_ID);
|
|
1877
|
-
const escrowTokenAccount = await deriveToken2022ATA(escrowAddress, mint);
|
|
1878
|
-
const agentTokenAccount = await deriveToken2022ATA(signer.address, mint);
|
|
1879
|
-
return this.execute(
|
|
1880
|
-
"completeEscrow",
|
|
1881
|
-
() => getCompleteEscrowInstruction({
|
|
1882
|
-
escrow: escrowAddress,
|
|
1883
|
-
reentrancyGuard,
|
|
1884
|
-
agent: signer.address,
|
|
1885
|
-
escrowTokenAccount,
|
|
1886
|
-
agentTokenAccount,
|
|
1887
|
-
authority: signer,
|
|
1888
|
-
tokenProgram: TOKEN_2022_PROGRAM_ADDRESS,
|
|
1889
|
-
resolutionNotes: "Work completed successfully"
|
|
1890
|
-
}),
|
|
1891
|
-
[signer]
|
|
1892
|
-
);
|
|
1893
|
-
}
|
|
1894
|
-
/**
|
|
1895
|
-
* Cancel an escrow - refunds the client
|
|
1896
|
-
*/
|
|
1897
|
-
async cancel(signer, taskId, params) {
|
|
1898
|
-
const mint = params.paymentToken ?? this.defaultPaymentToken;
|
|
1899
|
-
const escrowAddress = await deriveEscrowPdaFromTaskId(GHOSTSPEAK_PROGRAM_ID, taskId);
|
|
1900
|
-
const reentrancyGuard = await deriveReentrancyGuardPda(GHOSTSPEAK_PROGRAM_ID);
|
|
1901
|
-
const escrowTokenAccount = await deriveToken2022ATA(escrowAddress, mint);
|
|
1902
|
-
const clientRefundAccount = await deriveToken2022ATA(params.buyer, mint);
|
|
1903
|
-
return this.execute(
|
|
1904
|
-
"cancelEscrow",
|
|
1905
|
-
() => getCancelEscrowInstruction({
|
|
1906
|
-
escrow: escrowAddress,
|
|
1907
|
-
reentrancyGuard,
|
|
1908
|
-
authority: signer,
|
|
1909
|
-
clientRefundAccount,
|
|
1910
|
-
paymentToken: mint,
|
|
1911
|
-
cancellationReason: params.reason ?? "User cancelled",
|
|
1912
|
-
escrowTokenAccount,
|
|
1913
|
-
tokenProgram: TOKEN_2022_PROGRAM_ADDRESS
|
|
1914
|
-
}),
|
|
1915
|
-
[signer]
|
|
1916
|
-
);
|
|
1917
|
-
}
|
|
1918
|
-
/**
|
|
1919
|
-
* Dispute an escrow
|
|
1920
|
-
*/
|
|
1921
|
-
async dispute(signer, taskId, reason) {
|
|
1922
|
-
const escrowAddress = await deriveEscrowPdaFromTaskId(GHOSTSPEAK_PROGRAM_ID, taskId);
|
|
1923
|
-
const reentrancyGuard = await deriveReentrancyGuardPda(GHOSTSPEAK_PROGRAM_ID);
|
|
1924
|
-
return this.execute(
|
|
1925
|
-
"disputeEscrow",
|
|
1926
|
-
() => getDisputeEscrowInstruction({
|
|
1927
|
-
escrow: escrowAddress,
|
|
1928
|
-
reentrancyGuard,
|
|
1929
|
-
authority: signer,
|
|
1930
|
-
disputeReason: reason
|
|
1931
|
-
}),
|
|
1932
|
-
[signer]
|
|
1933
|
-
);
|
|
1934
|
-
}
|
|
1935
|
-
/**
|
|
1936
|
-
* Process partial refund
|
|
1937
|
-
*/
|
|
1938
|
-
async processPartialRefund(signer, taskId, refundAmount, totalAmount, clientAddress, agentAddress, paymentToken) {
|
|
1939
|
-
const mint = paymentToken ?? this.defaultPaymentToken;
|
|
1940
|
-
const escrowAddress = await deriveEscrowPdaFromTaskId(GHOSTSPEAK_PROGRAM_ID, taskId);
|
|
1941
|
-
const reentrancyGuard = await deriveReentrancyGuardPda(GHOSTSPEAK_PROGRAM_ID);
|
|
1942
|
-
const escrowTokenAccount = await deriveToken2022ATA(escrowAddress, mint);
|
|
1943
|
-
const clientRefundAccount = await deriveToken2022ATA(clientAddress, mint);
|
|
1944
|
-
const agentPaymentAccount = await deriveToken2022ATA(agentAddress, mint);
|
|
1945
|
-
return this.execute(
|
|
1946
|
-
"processPartialRefund",
|
|
1947
|
-
() => getProcessPartialRefundInstruction({
|
|
1948
|
-
escrow: escrowAddress,
|
|
1949
|
-
reentrancyGuard,
|
|
1950
|
-
escrowTokenAccount,
|
|
1951
|
-
clientRefundAccount,
|
|
1952
|
-
agentPaymentAccount,
|
|
1953
|
-
paymentToken: mint,
|
|
1954
|
-
authority: signer,
|
|
1955
|
-
tokenProgram: TOKEN_2022_PROGRAM_ADDRESS,
|
|
1956
|
-
clientRefundPercentage: Math.min(100, Math.max(0, Number((refundAmount * BigInt(100) / totalAmount).toString())))
|
|
1957
|
-
}),
|
|
1958
|
-
[signer]
|
|
1959
|
-
);
|
|
1960
|
-
}
|
|
1961
|
-
/**
|
|
1962
|
-
* Get escrow account
|
|
1963
|
-
*/
|
|
1964
|
-
async getEscrowAccount(address2) {
|
|
1965
|
-
return super.getAccount(address2, "getEscrowDecoder");
|
|
1966
|
-
}
|
|
1967
|
-
/**
|
|
1968
|
-
* Get escrow by taskId
|
|
1969
|
-
*/
|
|
1970
|
-
async getEscrowByTaskId(taskId) {
|
|
1971
|
-
const address2 = await deriveEscrowPdaFromTaskId(GHOSTSPEAK_PROGRAM_ID, taskId);
|
|
1972
|
-
return this.getEscrowAccount(address2);
|
|
1973
|
-
}
|
|
1974
|
-
/**
|
|
1975
|
-
* Get all escrows
|
|
1976
|
-
*/
|
|
1977
|
-
async getAllEscrows() {
|
|
1978
|
-
return this.getProgramAccounts("getEscrowDecoder");
|
|
1979
|
-
}
|
|
1980
|
-
/**
|
|
1981
|
-
* Get escrows by buyer
|
|
1982
|
-
*/
|
|
1983
|
-
async getEscrowsByBuyer(buyer) {
|
|
1984
|
-
const filters = [{
|
|
1985
|
-
memcmp: {
|
|
1986
|
-
offset: BigInt(8),
|
|
1987
|
-
// Skip discriminator
|
|
1988
|
-
bytes: buyer,
|
|
1989
|
-
encoding: "base58"
|
|
1990
|
-
}
|
|
1991
|
-
}];
|
|
1992
|
-
return this.getProgramAccounts("getEscrowDecoder", filters);
|
|
1993
|
-
}
|
|
1994
|
-
/**
|
|
1995
|
-
* Get escrows by seller
|
|
1996
|
-
*/
|
|
1997
|
-
async getEscrowsBySeller(seller) {
|
|
1998
|
-
const filters = [{
|
|
1999
|
-
memcmp: {
|
|
2000
|
-
offset: BigInt(40),
|
|
2001
|
-
// Skip discriminator + buyer
|
|
2002
|
-
bytes: seller,
|
|
2003
|
-
encoding: "base58"
|
|
2004
|
-
}
|
|
2005
|
-
}];
|
|
2006
|
-
return this.getProgramAccounts("getEscrowDecoder", filters);
|
|
2007
|
-
}
|
|
2008
|
-
/**
|
|
2009
|
-
* Get escrows by status
|
|
2010
|
-
*/
|
|
2011
|
-
async getEscrowsByStatus(status) {
|
|
2012
|
-
const escrows = await this.getAllEscrows();
|
|
2013
|
-
return escrows.filter(({ data }) => data.status === status);
|
|
2014
|
-
}
|
|
2015
|
-
// Helper methods
|
|
2016
|
-
/**
|
|
2017
|
-
* Default payment token - Token2022 native wSOL equivalent
|
|
2018
|
-
*/
|
|
2019
|
-
get defaultPaymentToken() {
|
|
2020
|
-
return NATIVE_MINT_ADDRESS;
|
|
2021
|
-
}
|
|
2022
|
-
};
|
|
2023
|
-
|
|
2024
|
-
// src/modules/channels/ChannelModule.ts
|
|
2025
|
-
var ChannelModule = class extends BaseModule {
|
|
2026
|
-
/**
|
|
2027
|
-
* Create a new channel
|
|
2028
|
-
*/
|
|
2029
|
-
async create(params) {
|
|
2030
|
-
const channelAddress = await this.deriveChannelPda(params.name);
|
|
2031
|
-
return this.execute(
|
|
2032
|
-
"createEnhancedChannel",
|
|
2033
|
-
() => getCreateEnhancedChannelInstructionAsync({
|
|
2034
|
-
channel: channelAddress,
|
|
2035
|
-
reentrancyGuard: this.systemProgramId,
|
|
2036
|
-
creator: params.signer,
|
|
2037
|
-
creatorAgent: params.signer.address,
|
|
2038
|
-
systemProgram: this.systemProgramId,
|
|
2039
|
-
channelId: params.name,
|
|
2040
|
-
participants: [params.signer.address],
|
|
2041
|
-
channelType: params.channelType,
|
|
2042
|
-
metadata: {
|
|
2043
|
-
name: params.name,
|
|
2044
|
-
description: params.description,
|
|
2045
|
-
avatarUrl: null,
|
|
2046
|
-
tags: [],
|
|
2047
|
-
settings: {
|
|
2048
|
-
allowFileSharing: true,
|
|
2049
|
-
allowExternalInvites: !params.isPrivate,
|
|
2050
|
-
messageRetentionDays: 30,
|
|
2051
|
-
maxMessageSize: 4096,
|
|
2052
|
-
requireEncryption: params.isPrivate ?? false,
|
|
2053
|
-
autoArchiveAfterDays: 365
|
|
2054
|
-
}
|
|
2055
|
-
}
|
|
2056
|
-
}),
|
|
2057
|
-
[params.signer]
|
|
2058
|
-
);
|
|
2059
|
-
}
|
|
2060
|
-
/**
|
|
2061
|
-
* Send a message to a channel
|
|
2062
|
-
*/
|
|
2063
|
-
async sendMessage(params) {
|
|
2064
|
-
const messageAddress = await this.deriveMessagePda(params.channelAddress, Date.now());
|
|
2065
|
-
return this.execute(
|
|
2066
|
-
"sendEnhancedMessage",
|
|
2067
|
-
() => getSendEnhancedMessageInstructionAsync({
|
|
2068
|
-
channel: params.channelAddress,
|
|
2069
|
-
message: messageAddress,
|
|
2070
|
-
reentrancyGuard: this.systemProgramId,
|
|
2071
|
-
sender: params.signer,
|
|
2072
|
-
systemProgram: this.systemProgramId,
|
|
2073
|
-
messageId: `msg_${Date.now()}`,
|
|
2074
|
-
content: params.content,
|
|
2075
|
-
messageType: params.messageType ?? 0 /* Text */,
|
|
2076
|
-
metadata: {
|
|
2077
|
-
replyTo: params.replyTo ?? null,
|
|
2078
|
-
threadId: null,
|
|
2079
|
-
attachments: params.attachmentUri ? [{ fileType: "application/octet-stream", fileSize: 0, fileHash: "", storageUrl: params.attachmentUri }] : [],
|
|
2080
|
-
mentions: [],
|
|
2081
|
-
reactions: []
|
|
2082
|
-
},
|
|
2083
|
-
isEncrypted: false
|
|
2084
|
-
}),
|
|
2085
|
-
[params.signer]
|
|
2086
|
-
);
|
|
2087
|
-
}
|
|
2088
|
-
/**
|
|
2089
|
-
* Join a channel
|
|
2090
|
-
*/
|
|
2091
|
-
async join(signer, channelAddress) {
|
|
2092
|
-
return this.execute(
|
|
2093
|
-
"joinChannel",
|
|
2094
|
-
() => getJoinChannelInstruction({
|
|
2095
|
-
channel: channelAddress,
|
|
2096
|
-
reentrancyGuard: this.systemProgramId,
|
|
2097
|
-
user: signer,
|
|
2098
|
-
userAgent: signer.address
|
|
2099
|
-
}),
|
|
2100
|
-
[signer]
|
|
2101
|
-
);
|
|
2102
|
-
}
|
|
2103
|
-
/**
|
|
2104
|
-
* Leave a channel
|
|
2105
|
-
*/
|
|
2106
|
-
async leave(signer, channelAddress) {
|
|
2107
|
-
return this.execute(
|
|
2108
|
-
"leaveChannel",
|
|
2109
|
-
() => getLeaveChannelInstruction({
|
|
2110
|
-
channel: channelAddress,
|
|
2111
|
-
reentrancyGuard: this.systemProgramId,
|
|
2112
|
-
user: signer
|
|
2113
|
-
}),
|
|
2114
|
-
[signer]
|
|
2115
|
-
);
|
|
2116
|
-
}
|
|
2117
|
-
/**
|
|
2118
|
-
* Update channel settings
|
|
2119
|
-
*/
|
|
2120
|
-
async updateSettings(signer, channelAddress, settings) {
|
|
2121
|
-
return this.execute(
|
|
2122
|
-
"updateChannelSettings",
|
|
2123
|
-
() => getUpdateChannelSettingsInstruction({
|
|
2124
|
-
channel: channelAddress,
|
|
2125
|
-
reentrancyGuard: this.systemProgramId,
|
|
2126
|
-
authority: signer,
|
|
2127
|
-
newMetadata: {
|
|
2128
|
-
name: settings.name ?? null,
|
|
2129
|
-
description: settings.description ?? null,
|
|
2130
|
-
avatarUrl: null,
|
|
2131
|
-
tags: [],
|
|
2132
|
-
settings: {
|
|
2133
|
-
allowFileSharing: true,
|
|
2134
|
-
allowExternalInvites: !settings.isPrivate,
|
|
2135
|
-
messageRetentionDays: 30,
|
|
2136
|
-
maxMessageSize: settings.maxMembers ? Number(settings.maxMembers) : 4096,
|
|
2137
|
-
requireEncryption: settings.isPrivate ?? false,
|
|
2138
|
-
autoArchiveAfterDays: 365
|
|
2139
|
-
}
|
|
2140
|
-
}
|
|
2141
|
-
}),
|
|
2142
|
-
[signer]
|
|
2143
|
-
);
|
|
2144
|
-
}
|
|
2145
|
-
/**
|
|
2146
|
-
* Add reaction to a message
|
|
2147
|
-
*/
|
|
2148
|
-
async addReaction(signer, messageAddress, emoji) {
|
|
2149
|
-
const channelAddress = await this.deriveChannelFromMessage(messageAddress);
|
|
2150
|
-
return this.execute(
|
|
2151
|
-
"addMessageReaction",
|
|
2152
|
-
() => getAddMessageReactionInstruction({
|
|
2153
|
-
channel: channelAddress,
|
|
2154
|
-
message: messageAddress,
|
|
2155
|
-
reentrancyGuard: this.systemProgramId,
|
|
2156
|
-
user: signer,
|
|
2157
|
-
reaction: emoji
|
|
2158
|
-
}),
|
|
2159
|
-
[signer]
|
|
2160
|
-
);
|
|
2161
|
-
}
|
|
2162
|
-
/**
|
|
2163
|
-
* Get channel account
|
|
2164
|
-
*/
|
|
2165
|
-
async getChannelAccount(address2) {
|
|
2166
|
-
return super.getAccount(address2, "getChannelDecoder");
|
|
2167
|
-
}
|
|
2168
|
-
/**
|
|
2169
|
-
* Get message account
|
|
2170
|
-
*/
|
|
2171
|
-
async getMessageAccount(address2) {
|
|
2172
|
-
return super.getAccount(address2, "getMessageDecoder");
|
|
2173
|
-
}
|
|
2174
|
-
/**
|
|
2175
|
-
* Get all channels
|
|
2176
|
-
*/
|
|
2177
|
-
async getAllChannels() {
|
|
2178
|
-
return this.getProgramAccounts("getChannelDecoder");
|
|
2179
|
-
}
|
|
2180
|
-
/**
|
|
2181
|
-
* Get public channels
|
|
2182
|
-
*/
|
|
2183
|
-
async getPublicChannels() {
|
|
2184
|
-
const channels = await this.getAllChannels();
|
|
2185
|
-
return channels.filter(({ data }) => !data.isPrivate);
|
|
2186
|
-
}
|
|
2187
|
-
/**
|
|
2188
|
-
* Get channels by creator
|
|
2189
|
-
*/
|
|
2190
|
-
async getChannelsByCreator(creator) {
|
|
2191
|
-
const filters = [{
|
|
2192
|
-
memcmp: {
|
|
2193
|
-
offset: BigInt(8),
|
|
2194
|
-
// Skip discriminator
|
|
2195
|
-
bytes: creator,
|
|
2196
|
-
encoding: "base58"
|
|
2197
|
-
}
|
|
2198
|
-
}];
|
|
2199
|
-
return this.getProgramAccounts("getChannelDecoder", filters);
|
|
2200
|
-
}
|
|
2201
|
-
/**
|
|
2202
|
-
* Get messages in channel
|
|
2203
|
-
*/
|
|
2204
|
-
async getChannelMessages(channelAddress) {
|
|
2205
|
-
const filters = [{
|
|
2206
|
-
memcmp: {
|
|
2207
|
-
offset: BigInt(8),
|
|
2208
|
-
// Skip discriminator
|
|
2209
|
-
bytes: channelAddress,
|
|
2210
|
-
encoding: "base58"
|
|
2211
|
-
}
|
|
2212
|
-
}];
|
|
2213
|
-
return this.getProgramAccounts("getMessageDecoder", filters);
|
|
2214
|
-
}
|
|
2215
|
-
// Helper methods
|
|
2216
|
-
async deriveChannelPda(name) {
|
|
2217
|
-
return await deriveChannelPda(GHOSTSPEAK_PROGRAM_ID, name);
|
|
2218
|
-
}
|
|
2219
|
-
async deriveMessagePda(channel, nonce) {
|
|
2220
|
-
return await deriveMessagePda(GHOSTSPEAK_PROGRAM_ID, channel, nonce);
|
|
2221
|
-
}
|
|
2222
|
-
async deriveChannelFromMessage(messageAddress) {
|
|
2223
|
-
return messageAddress;
|
|
2224
|
-
}
|
|
2225
|
-
get systemProgramId() {
|
|
2226
|
-
return "11111111111111111111111111111111";
|
|
2227
|
-
}
|
|
2228
|
-
};
|
|
2229
|
-
|
|
2230
|
-
// src/modules/marketplace/MarketplaceModule.ts
|
|
2231
|
-
var MarketplaceModule = class extends BaseModule {
|
|
2232
|
-
// =====================================================
|
|
2233
|
-
// DIRECT INSTRUCTION ACCESS
|
|
2234
|
-
// These methods provide direct access to generated instructions
|
|
2235
|
-
// with minimal wrapping for maximum flexibility
|
|
2236
|
-
// =====================================================
|
|
2237
|
-
/**
|
|
2238
|
-
* Get create service listing instruction
|
|
2239
|
-
*/
|
|
2240
|
-
getCreateServiceListingInstruction(params) {
|
|
2241
|
-
return getCreateServiceListingInstructionAsync(params);
|
|
2242
|
-
}
|
|
2243
|
-
/**
|
|
2244
|
-
* Get purchase service instruction
|
|
2245
|
-
*/
|
|
2246
|
-
getPurchaseServiceInstruction(params) {
|
|
2247
|
-
return getPurchaseServiceInstruction(params);
|
|
2248
|
-
}
|
|
2249
|
-
/**
|
|
2250
|
-
* Get create job posting instruction
|
|
2251
|
-
*/
|
|
2252
|
-
getCreateJobPostingInstruction(params) {
|
|
2253
|
-
return getCreateJobPostingInstructionAsync(params);
|
|
2254
|
-
}
|
|
2255
|
-
/**
|
|
2256
|
-
* Get apply to job instruction
|
|
2257
|
-
*/
|
|
2258
|
-
getApplyToJobInstruction(params) {
|
|
2259
|
-
return getApplyToJobInstructionAsync(params);
|
|
2260
|
-
}
|
|
2261
|
-
/**
|
|
2262
|
-
* Get accept job application instruction
|
|
2263
|
-
*/
|
|
2264
|
-
getAcceptJobApplicationInstruction(params) {
|
|
2265
|
-
return getAcceptJobApplicationInstructionAsync(params);
|
|
2266
|
-
}
|
|
2267
|
-
/**
|
|
2268
|
-
* Get create service auction instruction
|
|
2269
|
-
*/
|
|
2270
|
-
getCreateServiceAuctionInstruction(params) {
|
|
2271
|
-
return getCreateServiceAuctionInstructionAsync(params);
|
|
2272
|
-
}
|
|
2273
|
-
/**
|
|
2274
|
-
* Get place auction bid instruction
|
|
2275
|
-
*/
|
|
2276
|
-
getPlaceAuctionBidInstruction(params) {
|
|
2277
|
-
return getPlaceAuctionBidInstruction(params);
|
|
2278
|
-
}
|
|
2279
|
-
/**
|
|
2280
|
-
* Get finalize auction instruction
|
|
2281
|
-
*/
|
|
2282
|
-
getFinalizeAuctionInstruction(params) {
|
|
2283
|
-
return getFinalizeAuctionInstruction(params);
|
|
2284
|
-
}
|
|
2285
|
-
/**
|
|
2286
|
-
* Get update agent service instruction
|
|
2287
|
-
*/
|
|
2288
|
-
getUpdateAgentServiceInstruction(params) {
|
|
2289
|
-
return getUpdateAgentServiceInstruction(params);
|
|
2290
|
-
}
|
|
2291
|
-
// =====================================================
|
|
2292
|
-
// CONVENIENCE METHODS
|
|
2293
|
-
// These methods provide simplified access to common operations
|
|
2294
|
-
// =====================================================
|
|
2295
|
-
/**
|
|
2296
|
-
* Execute create service listing with convenience wrapper
|
|
2297
|
-
*/
|
|
2298
|
-
async createServiceListing(params) {
|
|
2299
|
-
const instruction = await this.getCreateServiceListingInstruction({
|
|
2300
|
-
agent: params.agentAddress,
|
|
2301
|
-
creator: params.signer,
|
|
2302
|
-
title: params.title,
|
|
2303
|
-
description: params.description,
|
|
2304
|
-
price: params.pricePerHour,
|
|
2305
|
-
tokenMint: this.nativeMint,
|
|
2306
|
-
serviceType: params.category,
|
|
2307
|
-
paymentToken: this.nativeMint,
|
|
2308
|
-
estimatedDelivery: Date.now() + 7 * 24 * 60 * 60 * 1e3,
|
|
2309
|
-
// 7 days
|
|
2310
|
-
tags: params.capabilities,
|
|
2311
|
-
listingId: `${params.agentAddress}_${params.title}`
|
|
2312
|
-
});
|
|
2313
|
-
return this.execute("createServiceListing", () => instruction, [params.signer]);
|
|
2314
|
-
}
|
|
2315
|
-
/**
|
|
2316
|
-
* Execute create job posting with convenience wrapper
|
|
2317
|
-
*/
|
|
2318
|
-
async createJobPosting(params) {
|
|
2319
|
-
const jobPostingAddress = await this.deriveJobPostingPda(params.signer.address, params.title);
|
|
2320
|
-
const instruction = await this.getCreateJobPostingInstruction({
|
|
2321
|
-
jobPosting: jobPostingAddress,
|
|
2322
|
-
employer: params.signer,
|
|
2323
|
-
title: params.title,
|
|
2324
|
-
description: params.description,
|
|
2325
|
-
requirements: [`Skills: ${params.requiredSkills.join(", ")}`],
|
|
2326
|
-
budget: params.budget,
|
|
2327
|
-
deadline: Date.now() + params.duration * 60 * 60 * 1e3,
|
|
2328
|
-
skillsNeeded: params.requiredSkills,
|
|
2329
|
-
budgetMin: params.budget,
|
|
2330
|
-
budgetMax: params.budget,
|
|
2331
|
-
paymentToken: this.nativeMint,
|
|
2332
|
-
jobType: params.category,
|
|
2333
|
-
experienceLevel: "intermediate"
|
|
2334
|
-
});
|
|
2335
|
-
return this.execute("createJobPosting", () => instruction, [params.signer]);
|
|
2336
|
-
}
|
|
2337
|
-
/**
|
|
2338
|
-
* Execute create service auction with convenience wrapper
|
|
2339
|
-
*/
|
|
2340
|
-
async createServiceAuction(params) {
|
|
2341
|
-
const auctionAddress = await this.deriveAuctionPda(params.serviceListingAddress);
|
|
2342
|
-
const instruction = await this.getCreateServiceAuctionInstruction({
|
|
2343
|
-
auction: auctionAddress,
|
|
2344
|
-
agent: params.serviceListingAddress,
|
|
2345
|
-
// Placeholder mapping
|
|
2346
|
-
userRegistry: auctionAddress,
|
|
2347
|
-
// Placeholder mapping
|
|
2348
|
-
creator: params.signer,
|
|
2349
|
-
auctionType: params.auctionType === "english" ? 0 /* English */ : 1 /* Dutch */,
|
|
2350
|
-
startingPrice: params.startingPrice,
|
|
2351
|
-
reservePrice: params.reservePrice,
|
|
2352
|
-
isReserveHidden: false,
|
|
2353
|
-
currentBid: BigInt(0),
|
|
2354
|
-
currentBidder: null,
|
|
2355
|
-
auctionEndTime: BigInt(Date.now() + params.duration * 60 * 60 * 1e3),
|
|
2356
|
-
minimumBidIncrement: BigInt(1e3),
|
|
2357
|
-
totalBids: 0,
|
|
2358
|
-
dutchConfig: null
|
|
2359
|
-
});
|
|
2360
|
-
return this.execute("createServiceAuction", () => instruction, [params.signer]);
|
|
2361
|
-
}
|
|
2362
|
-
// =====================================================
|
|
2363
|
-
// QUERY OPERATIONS
|
|
2364
|
-
// =====================================================
|
|
2365
|
-
/**
|
|
2366
|
-
* Get service listing account
|
|
2367
|
-
*/
|
|
2368
|
-
async getServiceListing(address2) {
|
|
2369
|
-
return super.getAccount(address2, "getServiceListingDecoder");
|
|
2370
|
-
}
|
|
2371
|
-
/**
|
|
2372
|
-
* Get job posting account
|
|
2373
|
-
*/
|
|
2374
|
-
async getJobPosting(address2) {
|
|
2375
|
-
return super.getAccount(address2, "getJobPostingDecoder");
|
|
2376
|
-
}
|
|
2377
|
-
/**
|
|
2378
|
-
* Get job application account
|
|
2379
|
-
*/
|
|
2380
|
-
async getJobApplication(address2) {
|
|
2381
|
-
return super.getAccount(address2, "getJobApplicationDecoder");
|
|
2382
|
-
}
|
|
2383
|
-
/**
|
|
2384
|
-
* Get auction account
|
|
2385
|
-
*/
|
|
2386
|
-
async getAuction(address2) {
|
|
2387
|
-
return super.getAccount(address2, "getAuctionMarketplaceDecoder");
|
|
2388
|
-
}
|
|
2389
|
-
/**
|
|
2390
|
-
* Get service purchase account
|
|
2391
|
-
*/
|
|
2392
|
-
async getServicePurchase(address2) {
|
|
2393
|
-
return super.getAccount(address2, "getServicePurchaseDecoder");
|
|
2394
|
-
}
|
|
2395
|
-
/**
|
|
2396
|
-
* Get all service listings
|
|
2397
|
-
*/
|
|
2398
|
-
async getAllServiceListings() {
|
|
2399
|
-
return this.getProgramAccounts("getServiceListingDecoder");
|
|
2400
|
-
}
|
|
2401
|
-
/**
|
|
2402
|
-
* Get service listings by provider
|
|
2403
|
-
*/
|
|
2404
|
-
async getServiceListingsByProvider(provider) {
|
|
2405
|
-
const filters = [{
|
|
2406
|
-
memcmp: {
|
|
2407
|
-
offset: BigInt(8),
|
|
2408
|
-
// Skip discriminator
|
|
2409
|
-
bytes: provider,
|
|
2410
|
-
encoding: "base58"
|
|
2411
|
-
}
|
|
2412
|
-
}];
|
|
2413
|
-
return this.getProgramAccounts("getServiceListingDecoder", filters);
|
|
2414
|
-
}
|
|
2415
|
-
/**
|
|
2416
|
-
* Get all job postings
|
|
2417
|
-
*/
|
|
2418
|
-
async getAllJobPostings() {
|
|
2419
|
-
return this.getProgramAccounts("getJobPostingDecoder");
|
|
2420
|
-
}
|
|
2421
|
-
/**
|
|
2422
|
-
* Get job postings by client
|
|
2423
|
-
*/
|
|
2424
|
-
async getJobPostingsByClient(client) {
|
|
2425
|
-
const filters = [{
|
|
2426
|
-
memcmp: {
|
|
2427
|
-
offset: BigInt(8),
|
|
2428
|
-
// Skip discriminator
|
|
2429
|
-
bytes: client,
|
|
2430
|
-
encoding: "base58"
|
|
2431
|
-
}
|
|
2432
|
-
}];
|
|
2433
|
-
return this.getProgramAccounts("getJobPostingDecoder", filters);
|
|
2434
|
-
}
|
|
2435
|
-
/**
|
|
2436
|
-
* Get applications for a job posting
|
|
2437
|
-
*/
|
|
2438
|
-
async getJobApplications(jobPostingAddress) {
|
|
2439
|
-
const filters = [{
|
|
2440
|
-
memcmp: {
|
|
2441
|
-
offset: BigInt(8),
|
|
2442
|
-
// Skip discriminator
|
|
2443
|
-
bytes: jobPostingAddress,
|
|
2444
|
-
encoding: "base58"
|
|
2445
|
-
}
|
|
2446
|
-
}];
|
|
2447
|
-
return this.getProgramAccounts("getJobApplicationDecoder", filters);
|
|
2448
|
-
}
|
|
2449
|
-
/**
|
|
2450
|
-
* Get all auctions
|
|
2451
|
-
*/
|
|
2452
|
-
async getAllAuctions() {
|
|
2453
|
-
return this.getProgramAccounts("getAuctionMarketplaceDecoder");
|
|
2454
|
-
}
|
|
2455
|
-
/**
|
|
2456
|
-
* Get service listing by ID (alias for getServiceListing)
|
|
2457
|
-
*/
|
|
2458
|
-
async getServiceById(address2) {
|
|
2459
|
-
return this.getServiceListing(address2);
|
|
2460
|
-
}
|
|
2461
|
-
/**
|
|
2462
|
-
* Execute purchase service with convenience wrapper
|
|
2463
|
-
*/
|
|
2464
|
-
async purchase(signer, params) {
|
|
2465
|
-
const serviceListing = params.listingId.split("_")[0];
|
|
2466
|
-
const servicePurchase = params.listingId.split("_")[0];
|
|
2467
|
-
const instruction = this.getPurchaseServiceInstruction({
|
|
2468
|
-
serviceListing,
|
|
2469
|
-
servicePurchase,
|
|
2470
|
-
buyer: signer,
|
|
2471
|
-
listingId: 0,
|
|
2472
|
-
// Placeholder - would be parsed from params
|
|
2473
|
-
quantity: Number(params.amount),
|
|
2474
|
-
requirements: [],
|
|
2475
|
-
customInstructions: "",
|
|
2476
|
-
deadline: Date.now() + 7 * 24 * 60 * 60 * 1e3
|
|
2477
|
-
});
|
|
2478
|
-
return this.execute("purchaseService", () => instruction, [signer]);
|
|
2479
|
-
}
|
|
2480
|
-
// =====================================================
|
|
2481
|
-
// HELPER METHODS
|
|
2482
|
-
// =====================================================
|
|
2483
|
-
async deriveJobPostingPda(client, title) {
|
|
2484
|
-
return await deriveJobPostingPda(GHOSTSPEAK_PROGRAM_ID, client, title);
|
|
2485
|
-
}
|
|
2486
|
-
async deriveAuctionPda(serviceListing) {
|
|
2487
|
-
return await deriveAuctionPda(GHOSTSPEAK_PROGRAM_ID, serviceListing);
|
|
2488
|
-
}
|
|
2489
|
-
get nativeMint() {
|
|
2490
|
-
return NATIVE_MINT_ADDRESS;
|
|
2491
|
-
}
|
|
2492
|
-
};
|
|
2493
|
-
|
|
2494
|
-
// src/modules/governance/GovernanceModule.ts
|
|
2495
|
-
var GovernanceModule = class extends BaseModule {
|
|
2496
|
-
// =====================================================
|
|
2497
|
-
// DIRECT INSTRUCTION ACCESS
|
|
2498
|
-
// These methods provide direct access to generated instructions
|
|
2499
|
-
// with minimal wrapping for maximum flexibility
|
|
2500
|
-
// =====================================================
|
|
2501
|
-
/**
|
|
2502
|
-
* Get initialize governance proposal instruction
|
|
2503
|
-
*/
|
|
2504
|
-
getInitializeGovernanceProposalInstruction(params) {
|
|
2505
|
-
return getInitializeGovernanceProposalInstructionAsync(params);
|
|
2506
|
-
}
|
|
2507
|
-
/**
|
|
2508
|
-
* Get cast vote instruction
|
|
2509
|
-
*/
|
|
2510
|
-
getCastVoteInstruction(params) {
|
|
2511
|
-
return getCastVoteInstruction(params);
|
|
2512
|
-
}
|
|
2513
|
-
/**
|
|
2514
|
-
* Get delegate vote instruction
|
|
2515
|
-
*/
|
|
2516
|
-
getDelegateVoteInstruction(params) {
|
|
2517
|
-
return getDelegateVoteInstruction(params);
|
|
2518
|
-
}
|
|
2519
|
-
/**
|
|
2520
|
-
* Get execute proposal instruction
|
|
2521
|
-
*/
|
|
2522
|
-
getExecuteProposalInstruction(params) {
|
|
2523
|
-
return getExecuteProposalInstruction(params);
|
|
2524
|
-
}
|
|
2525
|
-
/**
|
|
2526
|
-
* Get tally votes instruction
|
|
2527
|
-
*/
|
|
2528
|
-
getTallyVotesInstruction(params) {
|
|
2529
|
-
return getTallyVotesInstruction(params);
|
|
2530
|
-
}
|
|
2531
|
-
// =====================================================
|
|
2532
|
-
// CONVENIENCE METHODS
|
|
2533
|
-
// These methods provide simplified access to common operations
|
|
2534
|
-
// =====================================================
|
|
2535
|
-
/**
|
|
2536
|
-
* Create a new governance proposal
|
|
2537
|
-
*/
|
|
2538
|
-
async createProposal(params) {
|
|
2539
|
-
const proposalAddress = this.deriveProposalPda(params.signer.address, params.title);
|
|
2540
|
-
const instruction = await this.getInitializeGovernanceProposalInstruction({
|
|
2541
|
-
proposal: proposalAddress,
|
|
2542
|
-
proposer: params.signer,
|
|
2543
|
-
title: params.title,
|
|
2544
|
-
description: params.description,
|
|
2545
|
-
proposalType: { kind: params.proposalType, data: {} },
|
|
2546
|
-
executionParams: {
|
|
2547
|
-
instructions: [],
|
|
2548
|
-
accounts: [],
|
|
2549
|
-
targetProgram: proposalAddress,
|
|
2550
|
-
executeAfter: BigInt(params.executionDelay ?? 0)
|
|
2551
|
-
},
|
|
2552
|
-
proposalId: BigInt(Date.now())
|
|
2553
|
-
});
|
|
2554
|
-
return this.execute("createProposal", () => instruction, [params.signer]);
|
|
2555
|
-
}
|
|
2556
|
-
/**
|
|
2557
|
-
* Cast a vote on a proposal
|
|
2558
|
-
*/
|
|
2559
|
-
async vote(params) {
|
|
2560
|
-
const voteChoice = this.mapVoteChoice(params.choice);
|
|
2561
|
-
const instruction = this.getCastVoteInstruction({
|
|
2562
|
-
proposal: params.proposalAddress,
|
|
2563
|
-
voter: params.signer,
|
|
2564
|
-
voterTokenAccount: params.tokenAccount,
|
|
2565
|
-
voteChoice,
|
|
2566
|
-
reasoning: params.reasoning ?? null
|
|
2567
|
-
});
|
|
2568
|
-
return this.execute("castVote", () => instruction, [params.signer]);
|
|
2569
|
-
}
|
|
2570
|
-
/**
|
|
2571
|
-
* Delegate voting power to another address
|
|
2572
|
-
*/
|
|
2573
|
-
async delegateVotingPower(params) {
|
|
2574
|
-
const instruction = this.getDelegateVoteInstruction({
|
|
2575
|
-
delegator: params.signer,
|
|
2576
|
-
delegate: params.delegate,
|
|
2577
|
-
delegatorTokenAccount: params.tokenAccount,
|
|
2578
|
-
proposalId: BigInt(0),
|
|
2579
|
-
// 0 for all proposals
|
|
2580
|
-
scope: { kind: "All", value: void 0 },
|
|
2581
|
-
// Delegate for all proposals
|
|
2582
|
-
expiresAt: null
|
|
2583
|
-
});
|
|
2584
|
-
return this.execute("delegateVote", () => instruction, [params.signer]);
|
|
2585
|
-
}
|
|
2586
|
-
/**
|
|
2587
|
-
* Execute a passed proposal
|
|
2588
|
-
*/
|
|
2589
|
-
async executeProposal(params) {
|
|
2590
|
-
const instruction = this.getExecuteProposalInstruction({
|
|
2591
|
-
proposal: params.proposalAddress,
|
|
2592
|
-
executor: params.signer,
|
|
2593
|
-
targetProgram: this.getProgramId()
|
|
2594
|
-
});
|
|
2595
|
-
return this.execute("executeProposal", () => instruction, [params.signer]);
|
|
2596
|
-
}
|
|
2597
|
-
/**
|
|
2598
|
-
* Tally votes for a proposal
|
|
2599
|
-
*/
|
|
2600
|
-
async tallyVotes(params) {
|
|
2601
|
-
const instruction = this.getTallyVotesInstruction({
|
|
2602
|
-
proposal: params.proposalAddress,
|
|
2603
|
-
authority: params.signer
|
|
2604
|
-
});
|
|
2605
|
-
return this.execute("tallyVotes", () => instruction, [params.signer]);
|
|
2606
|
-
}
|
|
2607
|
-
// =====================================================
|
|
2608
|
-
// QUERY OPERATIONS
|
|
2609
|
-
// =====================================================
|
|
2610
|
-
/**
|
|
2611
|
-
* Get governance proposal account
|
|
2612
|
-
*/
|
|
2613
|
-
async getProposal(address2) {
|
|
2614
|
-
return super.getAccount(address2, "getGovernanceProposalDecoder");
|
|
2615
|
-
}
|
|
2616
|
-
/**
|
|
2617
|
-
* Get all active proposals
|
|
2618
|
-
*/
|
|
2619
|
-
async getActiveProposals() {
|
|
2620
|
-
return this.getProgramAccounts("getGovernanceProposalDecoder");
|
|
2621
|
-
}
|
|
2622
|
-
/**
|
|
2623
|
-
* Get proposals by proposer
|
|
2624
|
-
*/
|
|
2625
|
-
async getProposalsByProposer(proposer) {
|
|
2626
|
-
const filters = [{
|
|
2627
|
-
memcmp: {
|
|
2628
|
-
offset: BigInt(8),
|
|
2629
|
-
// Skip discriminator
|
|
2630
|
-
bytes: proposer,
|
|
2631
|
-
encoding: "base58"
|
|
2632
|
-
}
|
|
2633
|
-
}];
|
|
2634
|
-
return this.getProgramAccounts("getGovernanceProposalDecoder", filters);
|
|
2635
|
-
}
|
|
2636
|
-
/**
|
|
2637
|
-
* Get proposals by status
|
|
2638
|
-
*/
|
|
2639
|
-
async getProposalsByStatus(_status) {
|
|
2640
|
-
const allProposals = await this.getProgramAccounts("getGovernanceProposalDecoder");
|
|
2641
|
-
return allProposals.filter((_proposal) => {
|
|
2642
|
-
return allProposals.length > 0;
|
|
2643
|
-
});
|
|
2644
|
-
}
|
|
2645
|
-
// =====================================================
|
|
2646
|
-
// HELPER METHODS
|
|
2647
|
-
// =====================================================
|
|
2648
|
-
deriveProposalPda(proposer, title) {
|
|
2649
|
-
return `proposal_${proposer}_${title}`;
|
|
2650
|
-
}
|
|
2651
|
-
mapVoteChoice(choice) {
|
|
2652
|
-
switch (choice) {
|
|
2653
|
-
case "yes":
|
|
2654
|
-
return 0 /* For */;
|
|
2655
|
-
case "no":
|
|
2656
|
-
return 1 /* Against */;
|
|
2657
|
-
case "abstain":
|
|
2658
|
-
return 2 /* Abstain */;
|
|
2659
|
-
default:
|
|
2660
|
-
throw new Error(`Invalid vote choice: ${choice}`);
|
|
2661
|
-
}
|
|
2662
|
-
}
|
|
2663
|
-
};
|
|
2664
|
-
var Token2022Module = class extends BaseModule {
|
|
2665
|
-
// =====================================================
|
|
2666
|
-
// DIRECT INSTRUCTION ACCESS
|
|
2667
|
-
// These methods provide direct access to generated instructions
|
|
2668
|
-
// with minimal wrapping for maximum flexibility
|
|
2669
|
-
// =====================================================
|
|
2670
|
-
/**
|
|
2671
|
-
* Get create Token-2022 mint instruction
|
|
2672
|
-
*/
|
|
2673
|
-
getCreateToken2022MintInstruction(params) {
|
|
2674
|
-
return getCreateToken2022MintInstructionAsync({
|
|
2675
|
-
...params,
|
|
2676
|
-
// Ensure defaults for optional fields if passed as undefined
|
|
2677
|
-
transferFeeBasisPoints: params.transferFeeBasisPoints ?? null,
|
|
2678
|
-
maximumFee: params.maximumFee ?? null,
|
|
2679
|
-
transferFeeAuthority: params.transferFeeAuthority ?? null,
|
|
2680
|
-
withdrawWithheldAuthority: params.withdrawWithheldAuthority ?? null,
|
|
2681
|
-
autoApproveNewAccounts: params.autoApproveNewAccounts ?? null,
|
|
2682
|
-
auditorElgamalPubkey: params.auditorElgamalPubkey ?? null,
|
|
2683
|
-
interestRate: params.interestRate ?? null,
|
|
2684
|
-
rateAuthority: params.rateAuthority ?? null,
|
|
2685
|
-
closeAuthority: params.closeAuthority ?? null,
|
|
2686
|
-
defaultAccountState: params.defaultAccountState ?? null
|
|
2687
|
-
});
|
|
2688
|
-
}
|
|
2689
|
-
/**
|
|
2690
|
-
* Get initialize confidential transfer mint instruction
|
|
2691
|
-
*/
|
|
2692
|
-
getInitializeConfidentialTransferMintInstruction(params) {
|
|
2693
|
-
return getInitializeConfidentialTransferMintInstructionAsync(params);
|
|
2694
|
-
}
|
|
2695
|
-
/**
|
|
2696
|
-
* Get initialize interest bearing config instruction
|
|
2697
|
-
*/
|
|
2698
|
-
getInitializeInterestBearingConfigInstruction(params) {
|
|
2699
|
-
return getInitializeInterestBearingConfigInstructionAsync(params);
|
|
2700
|
-
}
|
|
2701
|
-
/**
|
|
2702
|
-
* Get initialize mint close authority instruction
|
|
2703
|
-
*/
|
|
2704
|
-
getInitializeMintCloseAuthorityInstruction(params) {
|
|
2705
|
-
return getInitializeMintCloseAuthorityInstructionAsync(params);
|
|
2706
|
-
}
|
|
2707
|
-
/**
|
|
2708
|
-
* Get initialize default account state instruction
|
|
2709
|
-
*/
|
|
2710
|
-
getInitializeDefaultAccountStateInstruction(params) {
|
|
2711
|
-
return getInitializeDefaultAccountStateInstructionAsync(params);
|
|
2712
|
-
}
|
|
2713
|
-
/**
|
|
2714
|
-
* Get approve extension instruction
|
|
2715
|
-
*/
|
|
2716
|
-
getApproveExtensionInstruction(params) {
|
|
2717
|
-
return getApproveExtensionInstruction(params);
|
|
2718
|
-
}
|
|
2719
|
-
// =====================================================
|
|
2720
|
-
// CONVENIENCE METHODS
|
|
2721
|
-
// These methods provide simplified access to common operations
|
|
2722
|
-
// =====================================================
|
|
2723
|
-
/**
|
|
2724
|
-
* Create a basic Token-2022 mint
|
|
2725
|
-
*/
|
|
2726
|
-
async createMint(params) {
|
|
2727
|
-
const mintKeypair = await this.generateKeypair();
|
|
2728
|
-
const instruction = await this.getCreateToken2022MintInstruction({
|
|
2729
|
-
authority: params.signer,
|
|
2730
|
-
agent: params.agentAddress,
|
|
2731
|
-
mint: mintKeypair,
|
|
2732
|
-
decimals: params.decimals,
|
|
2733
|
-
freezeAuthority: params.freezeAuthority ?? null,
|
|
2734
|
-
enableTransferFee: false,
|
|
2735
|
-
enableConfidentialTransfers: false,
|
|
2736
|
-
enableInterestBearing: false
|
|
2737
|
-
});
|
|
2738
|
-
return this.execute("createToken2022Mint", () => instruction, [params.signer, mintKeypair]);
|
|
2739
|
-
}
|
|
2740
|
-
async createMintWithTransferFees(params) {
|
|
2741
|
-
const mintKeypair = await this.generateKeypair();
|
|
2742
|
-
const mintInstruction = await this.getCreateToken2022MintInstruction({
|
|
2743
|
-
authority: params.signer,
|
|
2744
|
-
agent: params.agentAddress,
|
|
2745
|
-
mint: mintKeypair,
|
|
2746
|
-
decimals: params.decimals,
|
|
2747
|
-
freezeAuthority: null,
|
|
2748
|
-
enableTransferFee: true,
|
|
2749
|
-
enableConfidentialTransfers: false,
|
|
2750
|
-
enableInterestBearing: false,
|
|
2751
|
-
// Transfer fee extension params
|
|
2752
|
-
transferFeeBasisPoints: params.transferFeeBasisPoints,
|
|
2753
|
-
maximumFee: params.maxFee,
|
|
2754
|
-
transferFeeAuthority: params.signer.address,
|
|
2755
|
-
withdrawWithheldAuthority: params.withdrawWithheldAuthority ?? null
|
|
2756
|
-
});
|
|
2757
|
-
return this.execute("createMintWithFees", () => mintInstruction, [params.signer, mintKeypair]);
|
|
2758
|
-
}
|
|
2759
|
-
async createMintWithConfidentialTransfers(params) {
|
|
2760
|
-
const mintKeypair = await this.generateKeypair();
|
|
2761
|
-
const mintInstruction = await this.getCreateToken2022MintInstruction({
|
|
2762
|
-
authority: params.signer,
|
|
2763
|
-
agent: params.agentAddress,
|
|
2764
|
-
mint: mintKeypair,
|
|
2765
|
-
decimals: params.decimals,
|
|
2766
|
-
freezeAuthority: null,
|
|
2767
|
-
enableConfidentialTransfers: true,
|
|
2768
|
-
enableTransferFee: false,
|
|
2769
|
-
enableInterestBearing: false,
|
|
2770
|
-
// Confidential transfer params
|
|
2771
|
-
auditorElgamalPubkey: params.auditorElgamalPubkey ?? null,
|
|
2772
|
-
autoApproveNewAccounts: params.autoApproveNewAccounts ?? false
|
|
2773
|
-
});
|
|
2774
|
-
return this.execute("createMintWithConfidential", () => mintInstruction, [params.signer, mintKeypair]);
|
|
2775
|
-
}
|
|
2776
|
-
async createMintWithInterestBearing(params) {
|
|
2777
|
-
const mintKeypair = await this.generateKeypair();
|
|
2778
|
-
const mintInstruction = await this.getCreateToken2022MintInstruction({
|
|
2779
|
-
authority: params.signer,
|
|
2780
|
-
agent: params.agentAddress,
|
|
2781
|
-
mint: mintKeypair,
|
|
2782
|
-
decimals: params.decimals,
|
|
2783
|
-
freezeAuthority: null,
|
|
2784
|
-
enableConfidentialTransfers: false,
|
|
2785
|
-
enableTransferFee: false,
|
|
2786
|
-
enableInterestBearing: true,
|
|
2787
|
-
// Interest bearing params
|
|
2788
|
-
interestRate: params.interestRate,
|
|
2789
|
-
rateAuthority: params.rateAuthority ?? params.signer.address
|
|
2790
|
-
});
|
|
2791
|
-
return this.execute("createMintWithInterest", () => mintInstruction, [params.signer, mintKeypair]);
|
|
2792
|
-
}
|
|
2793
|
-
/**
|
|
2794
|
-
* Create a full-featured Token-2022 mint with all extensions
|
|
2795
|
-
*/
|
|
2796
|
-
async createAdvancedMint(params) {
|
|
2797
|
-
const mintKeypair = await this.generateKeypair();
|
|
2798
|
-
const instructions = [];
|
|
2799
|
-
instructions.push(async () => this.getCreateToken2022MintInstruction({
|
|
2800
|
-
authority: params.signer,
|
|
2801
|
-
agent: params.agentAddress,
|
|
2802
|
-
mint: mintKeypair,
|
|
2803
|
-
decimals: params.decimals,
|
|
2804
|
-
freezeAuthority: params.signer.address,
|
|
2805
|
-
enableConfidentialTransfers: true,
|
|
2806
|
-
enableTransferFee: true,
|
|
2807
|
-
enableInterestBearing: true,
|
|
2808
|
-
// Transfer fee params
|
|
2809
|
-
transferFeeBasisPoints: params.transferFeeBasisPoints,
|
|
2810
|
-
maximumFee: params.maxFee,
|
|
2811
|
-
transferFeeAuthority: params.signer.address,
|
|
2812
|
-
withdrawWithheldAuthority: params.signer.address,
|
|
2813
|
-
// Confidential transfer params
|
|
2814
|
-
auditorElgamalPubkey: null,
|
|
2815
|
-
autoApproveNewAccounts: params.autoApproveConfidential ?? false,
|
|
2816
|
-
// Interest bearing params
|
|
2817
|
-
interestRate: params.interestRate,
|
|
2818
|
-
rateAuthority: params.signer.address
|
|
2819
|
-
}));
|
|
2820
|
-
if (params.defaultAccountState) {
|
|
2821
|
-
instructions.push(async () => this.getInitializeDefaultAccountStateInstruction({
|
|
2822
|
-
mint: mintKeypair.address,
|
|
2823
|
-
authority: params.signer,
|
|
2824
|
-
state: params.defaultAccountState
|
|
2825
|
-
}));
|
|
2826
|
-
}
|
|
2827
|
-
return this.executeMultiple("createAdvancedMint", instructions, [params.signer, mintKeypair]);
|
|
2828
|
-
}
|
|
2829
|
-
// =====================================================
|
|
2830
|
-
// QUERY OPERATIONS
|
|
2831
|
-
// =====================================================
|
|
2832
|
-
/**
|
|
2833
|
-
* Get Token-2022 mint account
|
|
2834
|
-
*/
|
|
2835
|
-
async getMint(address2) {
|
|
2836
|
-
return super.getAccount(address2, "getMintDecoder");
|
|
2837
|
-
}
|
|
2838
|
-
/**
|
|
2839
|
-
* Get all Token-2022 mints created by this program
|
|
2840
|
-
*/
|
|
2841
|
-
async getAllMints() {
|
|
2842
|
-
return this.getProgramAccounts("getMintDecoder");
|
|
2843
|
-
}
|
|
2844
|
-
/**
|
|
2845
|
-
* Get mints by authority
|
|
2846
|
-
*/
|
|
2847
|
-
async getMintsByAuthority(authority) {
|
|
2848
|
-
const filters = [{
|
|
2849
|
-
memcmp: {
|
|
2850
|
-
offset: BigInt(8),
|
|
2851
|
-
// Skip discriminator
|
|
2852
|
-
bytes: authority,
|
|
2853
|
-
encoding: "base58"
|
|
2854
|
-
}
|
|
2855
|
-
}];
|
|
2856
|
-
return this.getProgramAccounts("getMintDecoder", filters);
|
|
2857
|
-
}
|
|
2858
|
-
// =====================================================
|
|
2859
|
-
// HELPER METHODS
|
|
2860
|
-
// =====================================================
|
|
2861
|
-
async generateKeypair() {
|
|
2862
|
-
return generateKeyPairSigner();
|
|
2863
|
-
}
|
|
2864
|
-
async executeMultiple(operation, instructionFactories, signers) {
|
|
2865
|
-
if (instructionFactories.length === 0) {
|
|
2866
|
-
throw new Error("No instruction factories provided");
|
|
2867
|
-
}
|
|
2868
|
-
const instructions = [];
|
|
2869
|
-
for (const factory of instructionFactories) {
|
|
2870
|
-
try {
|
|
2871
|
-
const instruction = await factory();
|
|
2872
|
-
instructions.push(instruction);
|
|
2873
|
-
} catch (error) {
|
|
2874
|
-
throw new Error(`Failed to create instruction: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2875
|
-
}
|
|
2876
|
-
}
|
|
2877
|
-
const firstInstruction = instructions[0];
|
|
2878
|
-
if (!firstInstruction) {
|
|
2879
|
-
throw new Error("First instruction is undefined");
|
|
2880
|
-
}
|
|
2881
|
-
return this.execute(operation, () => firstInstruction, signers);
|
|
2882
|
-
}
|
|
2883
|
-
};
|
|
2884
|
-
|
|
2885
|
-
export { AgentModule, BaseModule, ChannelModule, DEFAULT_IPFS_CONFIG, EscrowModule, GHOSTSPEAK_PROGRAM_ID, GovernanceModule, IPFSUtils, InstructionBuilder, MarketplaceModule, NETWORK_CONFIG, RpcClient, Token2022Module, createIPFSUtils, createMetadataUri, determineStorageMethod };
|
|
2886
|
-
//# sourceMappingURL=chunk-TVVGXYCI.js.map
|
|
2887
|
-
//# sourceMappingURL=chunk-TVVGXYCI.js.map
|