@talismn/solana 0.0.5 → 0.0.6
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/dist/index.d.mts +68 -0
- package/dist/index.d.ts +68 -0
- package/dist/index.js +199 -0
- package/dist/index.js.map +1 -0
- package/dist/{talismn-solana.esm.js → index.mjs} +83 -67
- package/dist/index.mjs.map +1 -0
- package/package.json +24 -21
- package/dist/declarations/src/index.d.ts +0 -4
- package/dist/declarations/src/utils/chains.d.ts +0 -3
- package/dist/declarations/src/utils/serialization.d.ts +0 -52
- package/dist/declarations/src/utils/signing.d.ts +0 -2
- package/dist/declarations/src/utils/transaction.d.ts +0 -7
- package/dist/talismn-solana.cjs.d.ts +0 -1
- package/dist/talismn-solana.cjs.dev.js +0 -162
- package/dist/talismn-solana.cjs.js +0 -7
- package/dist/talismn-solana.cjs.prod.js +0 -162
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { TransactionInstruction, Transaction, VersionedTransaction, Keypair } from '@solana/web3.js';
|
|
2
|
+
|
|
3
|
+
declare const SOLANA_CHAINS: readonly ["solana:mainnet", "solana:devnet", "solana:testnet", "solana:localnet"];
|
|
4
|
+
type SolanaChainId = (typeof SOLANA_CHAINS)[number];
|
|
5
|
+
declare const getSolNetworkId: (chain: SolanaChainId) => "solana-mainnet" | "solana-devnet" | "solana-testnet" | "solana-localnet";
|
|
6
|
+
|
|
7
|
+
declare const solInstructionToJson: (instruction: TransactionInstruction) => {
|
|
8
|
+
type: "solana-instruction";
|
|
9
|
+
value: {
|
|
10
|
+
programId: string;
|
|
11
|
+
keys: {
|
|
12
|
+
pubkey: string;
|
|
13
|
+
isSigner: boolean;
|
|
14
|
+
isWritable: boolean;
|
|
15
|
+
}[];
|
|
16
|
+
data: string;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
type SolInstructionJson = ReturnType<typeof solInstructionToJson>;
|
|
20
|
+
declare const solInstructionFromJson: (serialized: SolInstructionJson) => TransactionInstruction;
|
|
21
|
+
declare const serializeTransaction: (transaction: Transaction | VersionedTransaction) => string;
|
|
22
|
+
declare const deserializeTransaction: (transaction: string) => Transaction | VersionedTransaction;
|
|
23
|
+
declare const txToHumanJSON: (tx: string | Transaction | VersionedTransaction) => {
|
|
24
|
+
type: string;
|
|
25
|
+
version: 0 | "legacy";
|
|
26
|
+
signatures: string[];
|
|
27
|
+
recentBlockhash: string;
|
|
28
|
+
staticAccountKeys: string[];
|
|
29
|
+
addressTableLookups: {
|
|
30
|
+
accountKey: string;
|
|
31
|
+
writableIndexes: number[];
|
|
32
|
+
readonlyIndexes: number[];
|
|
33
|
+
}[];
|
|
34
|
+
instructions: {
|
|
35
|
+
programIdIndex: number;
|
|
36
|
+
programId: string;
|
|
37
|
+
accounts: {
|
|
38
|
+
index: number;
|
|
39
|
+
pubkey: string;
|
|
40
|
+
}[];
|
|
41
|
+
data: string;
|
|
42
|
+
}[];
|
|
43
|
+
} | {
|
|
44
|
+
type: string;
|
|
45
|
+
signatures: (string | null)[];
|
|
46
|
+
feePayer: string | null;
|
|
47
|
+
recentBlockhash: string | null;
|
|
48
|
+
instructions: {
|
|
49
|
+
programId: string;
|
|
50
|
+
accounts: {
|
|
51
|
+
pubkey: string;
|
|
52
|
+
isSigner: boolean;
|
|
53
|
+
isWritable: boolean;
|
|
54
|
+
}[];
|
|
55
|
+
data: string;
|
|
56
|
+
}[];
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
declare const getKeypair: (secretKey: Uint8Array) => Keypair;
|
|
60
|
+
|
|
61
|
+
declare const isVersionedTransaction: (transaction: Transaction | VersionedTransaction) => transaction is VersionedTransaction;
|
|
62
|
+
declare const parseTransactionInfo: (tx: Transaction | VersionedTransaction) => {
|
|
63
|
+
recentBlockhash: string | undefined;
|
|
64
|
+
address: string | undefined;
|
|
65
|
+
signature: string | null;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export { SOLANA_CHAINS, type SolInstructionJson, type SolanaChainId, deserializeTransaction, getKeypair, getSolNetworkId, isVersionedTransaction, parseTransactionInfo, serializeTransaction, solInstructionFromJson, solInstructionToJson, txToHumanJSON };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { TransactionInstruction, Transaction, VersionedTransaction, Keypair } from '@solana/web3.js';
|
|
2
|
+
|
|
3
|
+
declare const SOLANA_CHAINS: readonly ["solana:mainnet", "solana:devnet", "solana:testnet", "solana:localnet"];
|
|
4
|
+
type SolanaChainId = (typeof SOLANA_CHAINS)[number];
|
|
5
|
+
declare const getSolNetworkId: (chain: SolanaChainId) => "solana-mainnet" | "solana-devnet" | "solana-testnet" | "solana-localnet";
|
|
6
|
+
|
|
7
|
+
declare const solInstructionToJson: (instruction: TransactionInstruction) => {
|
|
8
|
+
type: "solana-instruction";
|
|
9
|
+
value: {
|
|
10
|
+
programId: string;
|
|
11
|
+
keys: {
|
|
12
|
+
pubkey: string;
|
|
13
|
+
isSigner: boolean;
|
|
14
|
+
isWritable: boolean;
|
|
15
|
+
}[];
|
|
16
|
+
data: string;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
type SolInstructionJson = ReturnType<typeof solInstructionToJson>;
|
|
20
|
+
declare const solInstructionFromJson: (serialized: SolInstructionJson) => TransactionInstruction;
|
|
21
|
+
declare const serializeTransaction: (transaction: Transaction | VersionedTransaction) => string;
|
|
22
|
+
declare const deserializeTransaction: (transaction: string) => Transaction | VersionedTransaction;
|
|
23
|
+
declare const txToHumanJSON: (tx: string | Transaction | VersionedTransaction) => {
|
|
24
|
+
type: string;
|
|
25
|
+
version: 0 | "legacy";
|
|
26
|
+
signatures: string[];
|
|
27
|
+
recentBlockhash: string;
|
|
28
|
+
staticAccountKeys: string[];
|
|
29
|
+
addressTableLookups: {
|
|
30
|
+
accountKey: string;
|
|
31
|
+
writableIndexes: number[];
|
|
32
|
+
readonlyIndexes: number[];
|
|
33
|
+
}[];
|
|
34
|
+
instructions: {
|
|
35
|
+
programIdIndex: number;
|
|
36
|
+
programId: string;
|
|
37
|
+
accounts: {
|
|
38
|
+
index: number;
|
|
39
|
+
pubkey: string;
|
|
40
|
+
}[];
|
|
41
|
+
data: string;
|
|
42
|
+
}[];
|
|
43
|
+
} | {
|
|
44
|
+
type: string;
|
|
45
|
+
signatures: (string | null)[];
|
|
46
|
+
feePayer: string | null;
|
|
47
|
+
recentBlockhash: string | null;
|
|
48
|
+
instructions: {
|
|
49
|
+
programId: string;
|
|
50
|
+
accounts: {
|
|
51
|
+
pubkey: string;
|
|
52
|
+
isSigner: boolean;
|
|
53
|
+
isWritable: boolean;
|
|
54
|
+
}[];
|
|
55
|
+
data: string;
|
|
56
|
+
}[];
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
declare const getKeypair: (secretKey: Uint8Array) => Keypair;
|
|
60
|
+
|
|
61
|
+
declare const isVersionedTransaction: (transaction: Transaction | VersionedTransaction) => transaction is VersionedTransaction;
|
|
62
|
+
declare const parseTransactionInfo: (tx: Transaction | VersionedTransaction) => {
|
|
63
|
+
recentBlockhash: string | undefined;
|
|
64
|
+
address: string | undefined;
|
|
65
|
+
signature: string | null;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export { SOLANA_CHAINS, type SolInstructionJson, type SolanaChainId, deserializeTransaction, getKeypair, getSolNetworkId, isVersionedTransaction, parseTransactionInfo, serializeTransaction, solInstructionFromJson, solInstructionToJson, txToHumanJSON };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
SOLANA_CHAINS: () => SOLANA_CHAINS,
|
|
24
|
+
deserializeTransaction: () => deserializeTransaction,
|
|
25
|
+
getKeypair: () => getKeypair,
|
|
26
|
+
getSolNetworkId: () => getSolNetworkId,
|
|
27
|
+
isVersionedTransaction: () => isVersionedTransaction,
|
|
28
|
+
parseTransactionInfo: () => parseTransactionInfo,
|
|
29
|
+
serializeTransaction: () => serializeTransaction,
|
|
30
|
+
solInstructionFromJson: () => solInstructionFromJson,
|
|
31
|
+
solInstructionToJson: () => solInstructionToJson,
|
|
32
|
+
txToHumanJSON: () => txToHumanJSON
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(index_exports);
|
|
35
|
+
|
|
36
|
+
// src/utils/chains.ts
|
|
37
|
+
var SOLANA_CHAINS = [
|
|
38
|
+
"solana:mainnet",
|
|
39
|
+
"solana:devnet",
|
|
40
|
+
"solana:testnet",
|
|
41
|
+
"solana:localnet"
|
|
42
|
+
];
|
|
43
|
+
var getSolNetworkId = (chain) => {
|
|
44
|
+
switch (chain) {
|
|
45
|
+
case "solana:mainnet":
|
|
46
|
+
return "solana-mainnet";
|
|
47
|
+
case "solana:devnet":
|
|
48
|
+
return "solana-devnet";
|
|
49
|
+
case "solana:testnet":
|
|
50
|
+
return "solana-testnet";
|
|
51
|
+
case "solana:localnet":
|
|
52
|
+
return "solana-localnet";
|
|
53
|
+
default:
|
|
54
|
+
throw new Error(`Unknown Solana chain: ${chain}`);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// src/utils/serialization.ts
|
|
59
|
+
var import_web3 = require("@solana/web3.js");
|
|
60
|
+
var import_crypto2 = require("@talismn/crypto");
|
|
61
|
+
|
|
62
|
+
// src/utils/transaction.ts
|
|
63
|
+
var import_crypto = require("@talismn/crypto");
|
|
64
|
+
var isVersionedTransaction = (transaction) => {
|
|
65
|
+
return "version" in transaction;
|
|
66
|
+
};
|
|
67
|
+
var parseTransactionInfo = (tx) => {
|
|
68
|
+
if (isVersionedTransaction(tx)) {
|
|
69
|
+
const recentBlockhash = tx.message.recentBlockhash;
|
|
70
|
+
const requiredSigners = tx.message.staticAccountKeys.filter(
|
|
71
|
+
(_, index) => tx.message.isAccountSigner(index)
|
|
72
|
+
);
|
|
73
|
+
const address = requiredSigners.length === 1 ? requiredSigners[0].toBase58() : void 0;
|
|
74
|
+
const sigBytes = tx.signatures.length ? tx.signatures[0] : null;
|
|
75
|
+
const signature = sigBytes && address && import_crypto.ed25519.verify(sigBytes, tx.message.serialize(), import_crypto.base58.decode(address)) ? import_crypto.base58.encode(sigBytes) : null;
|
|
76
|
+
return { recentBlockhash, address, signature };
|
|
77
|
+
} else {
|
|
78
|
+
const recentBlockhash = tx.recentBlockhash;
|
|
79
|
+
const address = tx.feePayer ? tx.feePayer.toBase58() : void 0;
|
|
80
|
+
const signature = tx.verifySignatures() ? import_crypto.base58.encode(tx.signature) : null;
|
|
81
|
+
return { recentBlockhash, address, signature };
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// src/utils/serialization.ts
|
|
86
|
+
var solInstructionToJson = (instruction) => {
|
|
87
|
+
return {
|
|
88
|
+
type: "solana-instruction",
|
|
89
|
+
value: {
|
|
90
|
+
programId: instruction.programId.toString(),
|
|
91
|
+
keys: instruction.keys.map((key) => ({
|
|
92
|
+
pubkey: key.pubkey.toString(),
|
|
93
|
+
isSigner: key.isSigner,
|
|
94
|
+
isWritable: key.isWritable
|
|
95
|
+
})),
|
|
96
|
+
data: instruction.data.toString("base64")
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
var solInstructionFromJson = (serialized) => {
|
|
101
|
+
if (serialized.type !== "solana-instruction")
|
|
102
|
+
throw new Error("Invalid serialized instruction type");
|
|
103
|
+
return {
|
|
104
|
+
programId: new import_web3.PublicKey(serialized.value.programId),
|
|
105
|
+
keys: serialized.value.keys.map((key) => ({
|
|
106
|
+
pubkey: new import_web3.PublicKey(key.pubkey),
|
|
107
|
+
isSigner: key.isSigner,
|
|
108
|
+
isWritable: key.isWritable
|
|
109
|
+
})),
|
|
110
|
+
data: Buffer.from(serialized.value.data, "base64")
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
var serializeTransaction = (transaction) => {
|
|
114
|
+
if (isVersionedTransaction(transaction)) {
|
|
115
|
+
return import_crypto2.base58.encode(transaction.serialize());
|
|
116
|
+
} else {
|
|
117
|
+
return import_crypto2.base58.encode(
|
|
118
|
+
transaction.serialize({ requireAllSignatures: false, verifySignatures: false })
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
var deserializeTransaction = (transaction) => {
|
|
123
|
+
const bytes = import_crypto2.base58.decode(transaction);
|
|
124
|
+
try {
|
|
125
|
+
return import_web3.VersionedTransaction.deserialize(bytes);
|
|
126
|
+
} catch {
|
|
127
|
+
return import_web3.Transaction.from(bytes);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
var txToHumanJSON = (tx) => {
|
|
131
|
+
if (typeof tx === "string") tx = deserializeTransaction(tx);
|
|
132
|
+
return isVersionedTransaction(tx) ? versionedTxToJSON(tx) : legacyTxToJSON(tx);
|
|
133
|
+
};
|
|
134
|
+
var legacyTxToJSON = (tx) => {
|
|
135
|
+
return {
|
|
136
|
+
type: "legacy",
|
|
137
|
+
signatures: tx.signatures.map((s) => s.signature ? import_crypto2.base58.encode(s.signature) : null),
|
|
138
|
+
feePayer: tx.feePayer?.toBase58() ?? null,
|
|
139
|
+
recentBlockhash: tx.recentBlockhash ?? null,
|
|
140
|
+
instructions: tx.instructions.map((ix) => ({
|
|
141
|
+
programId: ix.programId.toBase58(),
|
|
142
|
+
accounts: ix.keys.map((k) => ({
|
|
143
|
+
pubkey: k.pubkey.toBase58(),
|
|
144
|
+
isSigner: k.isSigner,
|
|
145
|
+
isWritable: k.isWritable
|
|
146
|
+
})),
|
|
147
|
+
data: import_crypto2.base58.encode(ix.data)
|
|
148
|
+
}))
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
var versionedTxToJSON = (tx) => {
|
|
152
|
+
const msg = tx.message;
|
|
153
|
+
const staticKeys = msg.staticAccountKeys;
|
|
154
|
+
return {
|
|
155
|
+
type: "versioned",
|
|
156
|
+
version: msg.version,
|
|
157
|
+
// usually 0
|
|
158
|
+
signatures: tx.signatures.map((sig) => import_crypto2.base58.encode(sig)),
|
|
159
|
+
recentBlockhash: msg.recentBlockhash,
|
|
160
|
+
staticAccountKeys: staticKeys.map((k) => k.toBase58()),
|
|
161
|
+
addressTableLookups: msg.addressTableLookups?.map((l) => ({
|
|
162
|
+
accountKey: l.accountKey.toBase58(),
|
|
163
|
+
writableIndexes: Array.from(l.writableIndexes),
|
|
164
|
+
readonlyIndexes: Array.from(l.readonlyIndexes)
|
|
165
|
+
})) ?? [],
|
|
166
|
+
instructions: msg.compiledInstructions.map((ix) => ({
|
|
167
|
+
programIdIndex: ix.programIdIndex,
|
|
168
|
+
programId: staticKeys[ix.programIdIndex]?.toBase58() ?? null,
|
|
169
|
+
accounts: ix.accountKeyIndexes.map((i) => ({
|
|
170
|
+
index: i,
|
|
171
|
+
pubkey: staticKeys[i]?.toBase58() ?? null
|
|
172
|
+
})),
|
|
173
|
+
data: import_crypto2.base58.encode(ix.data)
|
|
174
|
+
}))
|
|
175
|
+
};
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// src/utils/signing.ts
|
|
179
|
+
var import_web32 = require("@solana/web3.js");
|
|
180
|
+
var import_crypto3 = require("@talismn/crypto");
|
|
181
|
+
var getKeypair = (secretKey) => {
|
|
182
|
+
const publicKey = (0, import_crypto3.getPublicKeyFromSecret)(secretKey, "solana");
|
|
183
|
+
const fullScretKey = new Uint8Array([...secretKey, ...publicKey]);
|
|
184
|
+
return import_web32.Keypair.fromSecretKey(fullScretKey);
|
|
185
|
+
};
|
|
186
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
187
|
+
0 && (module.exports = {
|
|
188
|
+
SOLANA_CHAINS,
|
|
189
|
+
deserializeTransaction,
|
|
190
|
+
getKeypair,
|
|
191
|
+
getSolNetworkId,
|
|
192
|
+
isVersionedTransaction,
|
|
193
|
+
parseTransactionInfo,
|
|
194
|
+
serializeTransaction,
|
|
195
|
+
solInstructionFromJson,
|
|
196
|
+
solInstructionToJson,
|
|
197
|
+
txToHumanJSON
|
|
198
|
+
});
|
|
199
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/utils/chains.ts","../src/utils/serialization.ts","../src/utils/transaction.ts","../src/utils/signing.ts"],"sourcesContent":["export * from \"./utils/chains\"\nexport * from \"./utils/serialization\"\nexport * from \"./utils/signing\"\nexport * from \"./utils/transaction\"\n","export const SOLANA_CHAINS = [\n \"solana:mainnet\",\n \"solana:devnet\",\n \"solana:testnet\",\n \"solana:localnet\",\n] as const\n\nexport type SolanaChainId = (typeof SOLANA_CHAINS)[number]\n\nexport const getSolNetworkId = (chain: SolanaChainId) => {\n switch (chain) {\n case \"solana:mainnet\":\n return \"solana-mainnet\"\n case \"solana:devnet\":\n return \"solana-devnet\"\n case \"solana:testnet\":\n return \"solana-testnet\"\n case \"solana:localnet\":\n return \"solana-localnet\"\n default:\n throw new Error(`Unknown Solana chain: ${chain}`)\n }\n}\n","import {\n PublicKey,\n Transaction,\n type TransactionInstruction,\n VersionedTransaction,\n} from \"@solana/web3.js\"\nimport { base58 } from \"@talismn/crypto\"\n\nimport { isVersionedTransaction } from \"./transaction\"\n\n// Serialize TransactionInstruction to JSON\nexport const solInstructionToJson = (instruction: TransactionInstruction) => {\n return {\n type: \"solana-instruction\" as const,\n value: {\n programId: instruction.programId.toString(),\n keys: instruction.keys.map((key) => ({\n pubkey: key.pubkey.toString(),\n isSigner: key.isSigner,\n isWritable: key.isWritable,\n })),\n data: instruction.data.toString(\"base64\"),\n },\n }\n}\n\nexport type SolInstructionJson = ReturnType<typeof solInstructionToJson>\n\n// Deserialize JSON back to TransactionInstruction\nexport const solInstructionFromJson = (serialized: SolInstructionJson): TransactionInstruction => {\n if (serialized.type !== \"solana-instruction\")\n throw new Error(\"Invalid serialized instruction type\")\n\n return {\n programId: new PublicKey(serialized.value.programId),\n keys: serialized.value.keys.map((key) => ({\n pubkey: new PublicKey(key.pubkey),\n isSigner: key.isSigner,\n isWritable: key.isWritable,\n })),\n data: Buffer.from(serialized.value.data, \"base64\"),\n }\n}\n\nexport const serializeTransaction = (transaction: Transaction | VersionedTransaction): string => {\n if (isVersionedTransaction(transaction)) {\n return base58.encode(transaction.serialize())\n } else {\n return base58.encode(\n transaction.serialize({ requireAllSignatures: false, verifySignatures: false })\n )\n }\n}\n\nexport const deserializeTransaction = (transaction: string): Transaction | VersionedTransaction => {\n const bytes = base58.decode(transaction)\n\n try {\n return VersionedTransaction.deserialize(bytes)\n } catch {\n return Transaction.from(bytes)\n }\n}\n\nexport const txToHumanJSON = (tx: string | Transaction | VersionedTransaction) => {\n if (typeof tx === \"string\") tx = deserializeTransaction(tx)\n return isVersionedTransaction(tx) ? versionedTxToJSON(tx) : legacyTxToJSON(tx)\n}\n\nconst legacyTxToJSON = (tx: Transaction) => {\n return {\n type: \"legacy\",\n signatures: tx.signatures.map((s) => (s.signature ? base58.encode(s.signature) : null)),\n feePayer: tx.feePayer?.toBase58() ?? null,\n recentBlockhash: tx.recentBlockhash ?? null,\n instructions: tx.instructions.map((ix) => ({\n programId: ix.programId.toBase58(),\n accounts: ix.keys.map((k) => ({\n pubkey: k.pubkey.toBase58(),\n isSigner: k.isSigner,\n isWritable: k.isWritable,\n })),\n data: base58.encode(ix.data),\n })),\n }\n}\n\nconst versionedTxToJSON = (tx: VersionedTransaction) => {\n const msg = tx.message\n\n // ⚠️ NOTE: without address lookup table accounts we only have static keys.\n const staticKeys = msg.staticAccountKeys\n\n return {\n type: \"versioned\",\n version: msg.version, // usually 0\n signatures: tx.signatures.map((sig) => base58.encode(sig)),\n recentBlockhash: msg.recentBlockhash,\n staticAccountKeys: staticKeys.map((k) => k.toBase58()),\n addressTableLookups:\n msg.addressTableLookups?.map((l) => ({\n accountKey: l.accountKey.toBase58(),\n writableIndexes: Array.from(l.writableIndexes),\n readonlyIndexes: Array.from(l.readonlyIndexes),\n })) ?? [],\n instructions: msg.compiledInstructions.map((ix) => ({\n programIdIndex: ix.programIdIndex,\n programId: staticKeys[ix.programIdIndex]?.toBase58() ?? null,\n accounts: ix.accountKeyIndexes.map((i) => ({\n index: i,\n pubkey: staticKeys[i]?.toBase58() ?? null,\n })),\n data: base58.encode(ix.data),\n })),\n }\n}\n","import type { Transaction, VersionedTransaction } from \"@solana/web3.js\"\nimport { base58, ed25519 } from \"@talismn/crypto\"\n\nexport const isVersionedTransaction = (\n transaction: Transaction | VersionedTransaction\n): transaction is VersionedTransaction => {\n return \"version\" in transaction\n}\n\nexport const parseTransactionInfo = (tx: Transaction | VersionedTransaction) => {\n if (isVersionedTransaction(tx)) {\n const recentBlockhash = tx.message.recentBlockhash\n const requiredSigners = tx.message.staticAccountKeys.filter((_, index) =>\n tx.message.isAccountSigner(index)\n )\n const address = requiredSigners.length === 1 ? requiredSigners[0].toBase58() : undefined\n const sigBytes = tx.signatures.length ? tx.signatures[0] : null\n\n // signature might be an array of zeros, signature needs to be verified manually\n const signature =\n sigBytes &&\n address &&\n ed25519.verify(sigBytes, tx.message.serialize(), base58.decode(address))\n ? base58.encode(sigBytes)\n : null\n\n return { recentBlockhash, address, signature }\n } else {\n const recentBlockhash = tx.recentBlockhash\n const address = tx.feePayer ? tx.feePayer.toBase58() : undefined\n const signature = tx.verifySignatures() ? base58.encode(tx.signature!) : null\n\n return { recentBlockhash, address, signature }\n }\n}\n","import { Keypair } from \"@solana/web3.js\"\nimport { getPublicKeyFromSecret } from \"@talismn/crypto\"\n\nexport const getKeypair = (secretKey: Uint8Array): Keypair => {\n const publicKey = getPublicKeyFromSecret(secretKey, \"solana\")\n const fullScretKey = new Uint8Array([...secretKey, ...publicKey])\n return Keypair.fromSecretKey(fullScretKey)\n}\n"],"mappings":"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","names":["import_crypto","import_web3","import_crypto"]}
|
|
@@ -1,42 +1,63 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
// src/utils/chains.ts
|
|
2
|
+
var SOLANA_CHAINS = [
|
|
3
|
+
"solana:mainnet",
|
|
4
|
+
"solana:devnet",
|
|
5
|
+
"solana:testnet",
|
|
6
|
+
"solana:localnet"
|
|
7
|
+
];
|
|
8
|
+
var getSolNetworkId = (chain) => {
|
|
9
|
+
switch (chain) {
|
|
10
|
+
case "solana:mainnet":
|
|
11
|
+
return "solana-mainnet";
|
|
12
|
+
case "solana:devnet":
|
|
13
|
+
return "solana-devnet";
|
|
14
|
+
case "solana:testnet":
|
|
15
|
+
return "solana-testnet";
|
|
16
|
+
case "solana:localnet":
|
|
17
|
+
return "solana-localnet";
|
|
18
|
+
default:
|
|
19
|
+
throw new Error(`Unknown Solana chain: ${chain}`);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// src/utils/serialization.ts
|
|
24
|
+
import {
|
|
25
|
+
PublicKey,
|
|
26
|
+
Transaction,
|
|
27
|
+
VersionedTransaction
|
|
28
|
+
} from "@solana/web3.js";
|
|
29
|
+
import { base58 as base582 } from "@talismn/crypto";
|
|
3
30
|
|
|
4
|
-
|
|
31
|
+
// src/utils/transaction.ts
|
|
32
|
+
import { base58, ed25519 } from "@talismn/crypto";
|
|
33
|
+
var isVersionedTransaction = (transaction) => {
|
|
5
34
|
return "version" in transaction;
|
|
6
35
|
};
|
|
7
|
-
|
|
36
|
+
var parseTransactionInfo = (tx) => {
|
|
8
37
|
if (isVersionedTransaction(tx)) {
|
|
9
38
|
const recentBlockhash = tx.message.recentBlockhash;
|
|
10
|
-
const requiredSigners = tx.message.staticAccountKeys.filter(
|
|
11
|
-
|
|
39
|
+
const requiredSigners = tx.message.staticAccountKeys.filter(
|
|
40
|
+
(_, index) => tx.message.isAccountSigner(index)
|
|
41
|
+
);
|
|
42
|
+
const address = requiredSigners.length === 1 ? requiredSigners[0].toBase58() : void 0;
|
|
12
43
|
const sigBytes = tx.signatures.length ? tx.signatures[0] : null;
|
|
13
|
-
|
|
14
|
-
// signature might be an array of zeros, signature needs to be verified manually
|
|
15
44
|
const signature = sigBytes && address && ed25519.verify(sigBytes, tx.message.serialize(), base58.decode(address)) ? base58.encode(sigBytes) : null;
|
|
16
|
-
return {
|
|
17
|
-
recentBlockhash,
|
|
18
|
-
address,
|
|
19
|
-
signature
|
|
20
|
-
};
|
|
45
|
+
return { recentBlockhash, address, signature };
|
|
21
46
|
} else {
|
|
22
47
|
const recentBlockhash = tx.recentBlockhash;
|
|
23
|
-
const address = tx.feePayer ? tx.feePayer.toBase58() :
|
|
48
|
+
const address = tx.feePayer ? tx.feePayer.toBase58() : void 0;
|
|
24
49
|
const signature = tx.verifySignatures() ? base58.encode(tx.signature) : null;
|
|
25
|
-
return {
|
|
26
|
-
recentBlockhash,
|
|
27
|
-
address,
|
|
28
|
-
signature
|
|
29
|
-
};
|
|
50
|
+
return { recentBlockhash, address, signature };
|
|
30
51
|
}
|
|
31
52
|
};
|
|
32
53
|
|
|
33
|
-
//
|
|
34
|
-
|
|
54
|
+
// src/utils/serialization.ts
|
|
55
|
+
var solInstructionToJson = (instruction) => {
|
|
35
56
|
return {
|
|
36
57
|
type: "solana-instruction",
|
|
37
58
|
value: {
|
|
38
59
|
programId: instruction.programId.toString(),
|
|
39
|
-
keys: instruction.keys.map(key => ({
|
|
60
|
+
keys: instruction.keys.map((key) => ({
|
|
40
61
|
pubkey: key.pubkey.toString(),
|
|
41
62
|
isSigner: key.isSigner,
|
|
42
63
|
isWritable: key.isWritable
|
|
@@ -45,12 +66,12 @@ const solInstructionToJson = instruction => {
|
|
|
45
66
|
}
|
|
46
67
|
};
|
|
47
68
|
};
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
69
|
+
var solInstructionFromJson = (serialized) => {
|
|
70
|
+
if (serialized.type !== "solana-instruction")
|
|
71
|
+
throw new Error("Invalid serialized instruction type");
|
|
51
72
|
return {
|
|
52
73
|
programId: new PublicKey(serialized.value.programId),
|
|
53
|
-
keys: serialized.value.keys.map(key => ({
|
|
74
|
+
keys: serialized.value.keys.map((key) => ({
|
|
54
75
|
pubkey: new PublicKey(key.pubkey),
|
|
55
76
|
isSigner: key.isSigner,
|
|
56
77
|
isWritable: key.isWritable
|
|
@@ -58,94 +79,89 @@ const solInstructionFromJson = serialized => {
|
|
|
58
79
|
data: Buffer.from(serialized.value.data, "base64")
|
|
59
80
|
};
|
|
60
81
|
};
|
|
61
|
-
|
|
82
|
+
var serializeTransaction = (transaction) => {
|
|
62
83
|
if (isVersionedTransaction(transaction)) {
|
|
63
|
-
return
|
|
84
|
+
return base582.encode(transaction.serialize());
|
|
64
85
|
} else {
|
|
65
|
-
return
|
|
66
|
-
requireAllSignatures: false,
|
|
67
|
-
|
|
68
|
-
}));
|
|
86
|
+
return base582.encode(
|
|
87
|
+
transaction.serialize({ requireAllSignatures: false, verifySignatures: false })
|
|
88
|
+
);
|
|
69
89
|
}
|
|
70
90
|
};
|
|
71
|
-
|
|
72
|
-
const bytes =
|
|
91
|
+
var deserializeTransaction = (transaction) => {
|
|
92
|
+
const bytes = base582.decode(transaction);
|
|
73
93
|
try {
|
|
74
94
|
return VersionedTransaction.deserialize(bytes);
|
|
75
95
|
} catch {
|
|
76
96
|
return Transaction.from(bytes);
|
|
77
97
|
}
|
|
78
98
|
};
|
|
79
|
-
|
|
99
|
+
var txToHumanJSON = (tx) => {
|
|
80
100
|
if (typeof tx === "string") tx = deserializeTransaction(tx);
|
|
81
101
|
return isVersionedTransaction(tx) ? versionedTxToJSON(tx) : legacyTxToJSON(tx);
|
|
82
102
|
};
|
|
83
|
-
|
|
103
|
+
var legacyTxToJSON = (tx) => {
|
|
84
104
|
return {
|
|
85
105
|
type: "legacy",
|
|
86
|
-
signatures: tx.signatures.map(s => s.signature ?
|
|
106
|
+
signatures: tx.signatures.map((s) => s.signature ? base582.encode(s.signature) : null),
|
|
87
107
|
feePayer: tx.feePayer?.toBase58() ?? null,
|
|
88
108
|
recentBlockhash: tx.recentBlockhash ?? null,
|
|
89
|
-
instructions: tx.instructions.map(ix => ({
|
|
109
|
+
instructions: tx.instructions.map((ix) => ({
|
|
90
110
|
programId: ix.programId.toBase58(),
|
|
91
|
-
accounts: ix.keys.map(k => ({
|
|
111
|
+
accounts: ix.keys.map((k) => ({
|
|
92
112
|
pubkey: k.pubkey.toBase58(),
|
|
93
113
|
isSigner: k.isSigner,
|
|
94
114
|
isWritable: k.isWritable
|
|
95
115
|
})),
|
|
96
|
-
data:
|
|
116
|
+
data: base582.encode(ix.data)
|
|
97
117
|
}))
|
|
98
118
|
};
|
|
99
119
|
};
|
|
100
|
-
|
|
120
|
+
var versionedTxToJSON = (tx) => {
|
|
101
121
|
const msg = tx.message;
|
|
102
|
-
|
|
103
|
-
// ⚠️ NOTE: without address lookup table accounts we only have static keys.
|
|
104
122
|
const staticKeys = msg.staticAccountKeys;
|
|
105
123
|
return {
|
|
106
124
|
type: "versioned",
|
|
107
125
|
version: msg.version,
|
|
108
126
|
// usually 0
|
|
109
|
-
signatures: tx.signatures.map(sig =>
|
|
127
|
+
signatures: tx.signatures.map((sig) => base582.encode(sig)),
|
|
110
128
|
recentBlockhash: msg.recentBlockhash,
|
|
111
|
-
staticAccountKeys: staticKeys.map(k => k.toBase58()),
|
|
112
|
-
addressTableLookups: msg.addressTableLookups?.map(l => ({
|
|
129
|
+
staticAccountKeys: staticKeys.map((k) => k.toBase58()),
|
|
130
|
+
addressTableLookups: msg.addressTableLookups?.map((l) => ({
|
|
113
131
|
accountKey: l.accountKey.toBase58(),
|
|
114
132
|
writableIndexes: Array.from(l.writableIndexes),
|
|
115
133
|
readonlyIndexes: Array.from(l.readonlyIndexes)
|
|
116
134
|
})) ?? [],
|
|
117
|
-
instructions: msg.compiledInstructions.map(ix => ({
|
|
135
|
+
instructions: msg.compiledInstructions.map((ix) => ({
|
|
118
136
|
programIdIndex: ix.programIdIndex,
|
|
119
137
|
programId: staticKeys[ix.programIdIndex]?.toBase58() ?? null,
|
|
120
|
-
accounts: ix.accountKeyIndexes.map(i => ({
|
|
138
|
+
accounts: ix.accountKeyIndexes.map((i) => ({
|
|
121
139
|
index: i,
|
|
122
140
|
pubkey: staticKeys[i]?.toBase58() ?? null
|
|
123
141
|
})),
|
|
124
|
-
data:
|
|
142
|
+
data: base582.encode(ix.data)
|
|
125
143
|
}))
|
|
126
144
|
};
|
|
127
145
|
};
|
|
128
146
|
|
|
129
|
-
|
|
147
|
+
// src/utils/signing.ts
|
|
148
|
+
import { Keypair } from "@solana/web3.js";
|
|
149
|
+
import { getPublicKeyFromSecret } from "@talismn/crypto";
|
|
150
|
+
var getKeypair = (secretKey) => {
|
|
130
151
|
const publicKey = getPublicKeyFromSecret(secretKey, "solana");
|
|
131
152
|
const fullScretKey = new Uint8Array([...secretKey, ...publicKey]);
|
|
132
153
|
return Keypair.fromSecretKey(fullScretKey);
|
|
133
154
|
};
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
return "solana-localnet";
|
|
146
|
-
default:
|
|
147
|
-
throw new Error(`Unknown Solana chain: ${chain}`);
|
|
148
|
-
}
|
|
155
|
+
export {
|
|
156
|
+
SOLANA_CHAINS,
|
|
157
|
+
deserializeTransaction,
|
|
158
|
+
getKeypair,
|
|
159
|
+
getSolNetworkId,
|
|
160
|
+
isVersionedTransaction,
|
|
161
|
+
parseTransactionInfo,
|
|
162
|
+
serializeTransaction,
|
|
163
|
+
solInstructionFromJson,
|
|
164
|
+
solInstructionToJson,
|
|
165
|
+
txToHumanJSON
|
|
149
166
|
};
|
|
150
|
-
|
|
151
|
-
export { SOLANA_CHAINS, deserializeTransaction, getKeypair, getSolNetworkId, isVersionedTransaction, parseTransactionInfo, serializeTransaction, solInstructionFromJson, solInstructionToJson, txToHumanJSON };
|
|
167
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/chains.ts","../src/utils/serialization.ts","../src/utils/transaction.ts","../src/utils/signing.ts"],"sourcesContent":["export const SOLANA_CHAINS = [\n \"solana:mainnet\",\n \"solana:devnet\",\n \"solana:testnet\",\n \"solana:localnet\",\n] as const\n\nexport type SolanaChainId = (typeof SOLANA_CHAINS)[number]\n\nexport const getSolNetworkId = (chain: SolanaChainId) => {\n switch (chain) {\n case \"solana:mainnet\":\n return \"solana-mainnet\"\n case \"solana:devnet\":\n return \"solana-devnet\"\n case \"solana:testnet\":\n return \"solana-testnet\"\n case \"solana:localnet\":\n return \"solana-localnet\"\n default:\n throw new Error(`Unknown Solana chain: ${chain}`)\n }\n}\n","import {\n PublicKey,\n Transaction,\n type TransactionInstruction,\n VersionedTransaction,\n} from \"@solana/web3.js\"\nimport { base58 } from \"@talismn/crypto\"\n\nimport { isVersionedTransaction } from \"./transaction\"\n\n// Serialize TransactionInstruction to JSON\nexport const solInstructionToJson = (instruction: TransactionInstruction) => {\n return {\n type: \"solana-instruction\" as const,\n value: {\n programId: instruction.programId.toString(),\n keys: instruction.keys.map((key) => ({\n pubkey: key.pubkey.toString(),\n isSigner: key.isSigner,\n isWritable: key.isWritable,\n })),\n data: instruction.data.toString(\"base64\"),\n },\n }\n}\n\nexport type SolInstructionJson = ReturnType<typeof solInstructionToJson>\n\n// Deserialize JSON back to TransactionInstruction\nexport const solInstructionFromJson = (serialized: SolInstructionJson): TransactionInstruction => {\n if (serialized.type !== \"solana-instruction\")\n throw new Error(\"Invalid serialized instruction type\")\n\n return {\n programId: new PublicKey(serialized.value.programId),\n keys: serialized.value.keys.map((key) => ({\n pubkey: new PublicKey(key.pubkey),\n isSigner: key.isSigner,\n isWritable: key.isWritable,\n })),\n data: Buffer.from(serialized.value.data, \"base64\"),\n }\n}\n\nexport const serializeTransaction = (transaction: Transaction | VersionedTransaction): string => {\n if (isVersionedTransaction(transaction)) {\n return base58.encode(transaction.serialize())\n } else {\n return base58.encode(\n transaction.serialize({ requireAllSignatures: false, verifySignatures: false })\n )\n }\n}\n\nexport const deserializeTransaction = (transaction: string): Transaction | VersionedTransaction => {\n const bytes = base58.decode(transaction)\n\n try {\n return VersionedTransaction.deserialize(bytes)\n } catch {\n return Transaction.from(bytes)\n }\n}\n\nexport const txToHumanJSON = (tx: string | Transaction | VersionedTransaction) => {\n if (typeof tx === \"string\") tx = deserializeTransaction(tx)\n return isVersionedTransaction(tx) ? versionedTxToJSON(tx) : legacyTxToJSON(tx)\n}\n\nconst legacyTxToJSON = (tx: Transaction) => {\n return {\n type: \"legacy\",\n signatures: tx.signatures.map((s) => (s.signature ? base58.encode(s.signature) : null)),\n feePayer: tx.feePayer?.toBase58() ?? null,\n recentBlockhash: tx.recentBlockhash ?? null,\n instructions: tx.instructions.map((ix) => ({\n programId: ix.programId.toBase58(),\n accounts: ix.keys.map((k) => ({\n pubkey: k.pubkey.toBase58(),\n isSigner: k.isSigner,\n isWritable: k.isWritable,\n })),\n data: base58.encode(ix.data),\n })),\n }\n}\n\nconst versionedTxToJSON = (tx: VersionedTransaction) => {\n const msg = tx.message\n\n // ⚠️ NOTE: without address lookup table accounts we only have static keys.\n const staticKeys = msg.staticAccountKeys\n\n return {\n type: \"versioned\",\n version: msg.version, // usually 0\n signatures: tx.signatures.map((sig) => base58.encode(sig)),\n recentBlockhash: msg.recentBlockhash,\n staticAccountKeys: staticKeys.map((k) => k.toBase58()),\n addressTableLookups:\n msg.addressTableLookups?.map((l) => ({\n accountKey: l.accountKey.toBase58(),\n writableIndexes: Array.from(l.writableIndexes),\n readonlyIndexes: Array.from(l.readonlyIndexes),\n })) ?? [],\n instructions: msg.compiledInstructions.map((ix) => ({\n programIdIndex: ix.programIdIndex,\n programId: staticKeys[ix.programIdIndex]?.toBase58() ?? null,\n accounts: ix.accountKeyIndexes.map((i) => ({\n index: i,\n pubkey: staticKeys[i]?.toBase58() ?? null,\n })),\n data: base58.encode(ix.data),\n })),\n }\n}\n","import type { Transaction, VersionedTransaction } from \"@solana/web3.js\"\nimport { base58, ed25519 } from \"@talismn/crypto\"\n\nexport const isVersionedTransaction = (\n transaction: Transaction | VersionedTransaction\n): transaction is VersionedTransaction => {\n return \"version\" in transaction\n}\n\nexport const parseTransactionInfo = (tx: Transaction | VersionedTransaction) => {\n if (isVersionedTransaction(tx)) {\n const recentBlockhash = tx.message.recentBlockhash\n const requiredSigners = tx.message.staticAccountKeys.filter((_, index) =>\n tx.message.isAccountSigner(index)\n )\n const address = requiredSigners.length === 1 ? requiredSigners[0].toBase58() : undefined\n const sigBytes = tx.signatures.length ? tx.signatures[0] : null\n\n // signature might be an array of zeros, signature needs to be verified manually\n const signature =\n sigBytes &&\n address &&\n ed25519.verify(sigBytes, tx.message.serialize(), base58.decode(address))\n ? base58.encode(sigBytes)\n : null\n\n return { recentBlockhash, address, signature }\n } else {\n const recentBlockhash = tx.recentBlockhash\n const address = tx.feePayer ? tx.feePayer.toBase58() : undefined\n const signature = tx.verifySignatures() ? base58.encode(tx.signature!) : null\n\n return { recentBlockhash, address, signature }\n }\n}\n","import { Keypair } from \"@solana/web3.js\"\nimport { getPublicKeyFromSecret } from \"@talismn/crypto\"\n\nexport const getKeypair = (secretKey: Uint8Array): Keypair => {\n const publicKey = getPublicKeyFromSecret(secretKey, \"solana\")\n const fullScretKey = new Uint8Array([...secretKey, ...publicKey])\n return Keypair.fromSecretKey(fullScretKey)\n}\n"],"mappings":"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","names":["base58","base58"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@talismn/solana",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"author": "Talisman",
|
|
5
5
|
"homepage": "https://talisman.xyz",
|
|
6
6
|
"license": "GPL-3.0-or-later",
|
|
@@ -10,39 +10,42 @@
|
|
|
10
10
|
"repository": {
|
|
11
11
|
"directory": "packages/solana",
|
|
12
12
|
"type": "git",
|
|
13
|
-
"url": "https://github.com/
|
|
13
|
+
"url": "https://github.com/TalismanSociety/talisman.git"
|
|
14
14
|
},
|
|
15
|
-
"main": "dist/
|
|
16
|
-
"module": "dist/
|
|
15
|
+
"main": "./dist/index.js",
|
|
16
|
+
"module": "./dist/index.mjs",
|
|
17
17
|
"files": [
|
|
18
|
-
"
|
|
18
|
+
"dist"
|
|
19
19
|
],
|
|
20
20
|
"engines": {
|
|
21
21
|
"node": ">=20"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@solana/web3.js": "^1.98.2",
|
|
25
|
-
"
|
|
26
|
-
"@talismn/crypto": "0.3.0"
|
|
25
|
+
"@talismn/crypto": "0.3.1"
|
|
27
26
|
},
|
|
28
27
|
"devDependencies": {
|
|
29
|
-
"@types/jest": "^29.5.14",
|
|
30
|
-
"eslint": "^8.57.1",
|
|
31
|
-
"jest": "^29.7",
|
|
32
|
-
"ts-jest": "^29.2.5",
|
|
33
28
|
"typescript": "^5.6.3",
|
|
34
|
-
"@talismn/tsconfig": "0.0.
|
|
35
|
-
"@talismn/eslint-config": "0.0.3"
|
|
29
|
+
"@talismn/tsconfig": "0.0.4"
|
|
36
30
|
},
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
"@talismn/
|
|
41
|
-
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"@talismn/source": "./src/index.ts",
|
|
35
|
+
"import": {
|
|
36
|
+
"types": "./dist/index.d.mts",
|
|
37
|
+
"default": "./dist/index.mjs"
|
|
38
|
+
},
|
|
39
|
+
"require": {
|
|
40
|
+
"types": "./dist/index.d.ts",
|
|
41
|
+
"default": "./dist/index.js"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
42
44
|
},
|
|
43
45
|
"scripts": {
|
|
44
|
-
"test": "
|
|
45
|
-
"
|
|
46
|
-
"
|
|
46
|
+
"test": "vitest run",
|
|
47
|
+
"clean": "rm -rf dist .turbo node_modules",
|
|
48
|
+
"build": "tsup --silent",
|
|
49
|
+
"typecheck": "tsc --noEmit"
|
|
47
50
|
}
|
|
48
51
|
}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
export declare const SOLANA_CHAINS: readonly ["solana:mainnet", "solana:devnet", "solana:testnet", "solana:localnet"];
|
|
2
|
-
export type SolanaChainId = (typeof SOLANA_CHAINS)[number];
|
|
3
|
-
export declare const getSolNetworkId: (chain: SolanaChainId) => "solana-mainnet" | "solana-devnet" | "solana-testnet" | "solana-localnet";
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { Transaction, TransactionInstruction, VersionedTransaction } from "@solana/web3.js";
|
|
2
|
-
export declare const solInstructionToJson: (instruction: TransactionInstruction) => {
|
|
3
|
-
type: "solana-instruction";
|
|
4
|
-
value: {
|
|
5
|
-
programId: string;
|
|
6
|
-
keys: {
|
|
7
|
-
pubkey: string;
|
|
8
|
-
isSigner: boolean;
|
|
9
|
-
isWritable: boolean;
|
|
10
|
-
}[];
|
|
11
|
-
data: string;
|
|
12
|
-
};
|
|
13
|
-
};
|
|
14
|
-
export type SolInstructionJson = ReturnType<typeof solInstructionToJson>;
|
|
15
|
-
export declare const solInstructionFromJson: (serialized: SolInstructionJson) => TransactionInstruction;
|
|
16
|
-
export declare const serializeTransaction: (transaction: Transaction | VersionedTransaction) => string;
|
|
17
|
-
export declare const deserializeTransaction: (transaction: string) => Transaction | VersionedTransaction;
|
|
18
|
-
export declare const txToHumanJSON: (tx: string | Transaction | VersionedTransaction) => {
|
|
19
|
-
type: string;
|
|
20
|
-
version: 0 | "legacy";
|
|
21
|
-
signatures: string[];
|
|
22
|
-
recentBlockhash: string;
|
|
23
|
-
staticAccountKeys: string[];
|
|
24
|
-
addressTableLookups: {
|
|
25
|
-
accountKey: string;
|
|
26
|
-
writableIndexes: number[];
|
|
27
|
-
readonlyIndexes: number[];
|
|
28
|
-
}[];
|
|
29
|
-
instructions: {
|
|
30
|
-
programIdIndex: number;
|
|
31
|
-
programId: string;
|
|
32
|
-
accounts: {
|
|
33
|
-
index: number;
|
|
34
|
-
pubkey: string;
|
|
35
|
-
}[];
|
|
36
|
-
data: string;
|
|
37
|
-
}[];
|
|
38
|
-
} | {
|
|
39
|
-
type: string;
|
|
40
|
-
signatures: (string | null)[];
|
|
41
|
-
feePayer: string | null;
|
|
42
|
-
recentBlockhash: string | null;
|
|
43
|
-
instructions: {
|
|
44
|
-
programId: string;
|
|
45
|
-
accounts: {
|
|
46
|
-
pubkey: string;
|
|
47
|
-
isSigner: boolean;
|
|
48
|
-
isWritable: boolean;
|
|
49
|
-
}[];
|
|
50
|
-
data: string;
|
|
51
|
-
}[];
|
|
52
|
-
};
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { Transaction, VersionedTransaction } from "@solana/web3.js";
|
|
2
|
-
export declare const isVersionedTransaction: (transaction: Transaction | VersionedTransaction) => transaction is VersionedTransaction;
|
|
3
|
-
export declare const parseTransactionInfo: (tx: Transaction | VersionedTransaction) => {
|
|
4
|
-
recentBlockhash: string | undefined;
|
|
5
|
-
address: string | undefined;
|
|
6
|
-
signature: string | null;
|
|
7
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./declarations/src/index";
|
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var web3_js = require('@solana/web3.js');
|
|
4
|
-
var crypto = require('@talismn/crypto');
|
|
5
|
-
|
|
6
|
-
const isVersionedTransaction = transaction => {
|
|
7
|
-
return "version" in transaction;
|
|
8
|
-
};
|
|
9
|
-
const parseTransactionInfo = tx => {
|
|
10
|
-
if (isVersionedTransaction(tx)) {
|
|
11
|
-
const recentBlockhash = tx.message.recentBlockhash;
|
|
12
|
-
const requiredSigners = tx.message.staticAccountKeys.filter((_, index) => tx.message.isAccountSigner(index));
|
|
13
|
-
const address = requiredSigners.length === 1 ? requiredSigners[0].toBase58() : undefined;
|
|
14
|
-
const sigBytes = tx.signatures.length ? tx.signatures[0] : null;
|
|
15
|
-
|
|
16
|
-
// signature might be an array of zeros, signature needs to be verified manually
|
|
17
|
-
const signature = sigBytes && address && crypto.ed25519.verify(sigBytes, tx.message.serialize(), crypto.base58.decode(address)) ? crypto.base58.encode(sigBytes) : null;
|
|
18
|
-
return {
|
|
19
|
-
recentBlockhash,
|
|
20
|
-
address,
|
|
21
|
-
signature
|
|
22
|
-
};
|
|
23
|
-
} else {
|
|
24
|
-
const recentBlockhash = tx.recentBlockhash;
|
|
25
|
-
const address = tx.feePayer ? tx.feePayer.toBase58() : undefined;
|
|
26
|
-
const signature = tx.verifySignatures() ? crypto.base58.encode(tx.signature) : null;
|
|
27
|
-
return {
|
|
28
|
-
recentBlockhash,
|
|
29
|
-
address,
|
|
30
|
-
signature
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
// Serialize TransactionInstruction to JSON
|
|
36
|
-
const solInstructionToJson = instruction => {
|
|
37
|
-
return {
|
|
38
|
-
type: "solana-instruction",
|
|
39
|
-
value: {
|
|
40
|
-
programId: instruction.programId.toString(),
|
|
41
|
-
keys: instruction.keys.map(key => ({
|
|
42
|
-
pubkey: key.pubkey.toString(),
|
|
43
|
-
isSigner: key.isSigner,
|
|
44
|
-
isWritable: key.isWritable
|
|
45
|
-
})),
|
|
46
|
-
data: instruction.data.toString("base64")
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
};
|
|
50
|
-
// Deserialize JSON back to TransactionInstruction
|
|
51
|
-
const solInstructionFromJson = serialized => {
|
|
52
|
-
if (serialized.type !== "solana-instruction") throw new Error("Invalid serialized instruction type");
|
|
53
|
-
return {
|
|
54
|
-
programId: new web3_js.PublicKey(serialized.value.programId),
|
|
55
|
-
keys: serialized.value.keys.map(key => ({
|
|
56
|
-
pubkey: new web3_js.PublicKey(key.pubkey),
|
|
57
|
-
isSigner: key.isSigner,
|
|
58
|
-
isWritable: key.isWritable
|
|
59
|
-
})),
|
|
60
|
-
data: Buffer.from(serialized.value.data, "base64")
|
|
61
|
-
};
|
|
62
|
-
};
|
|
63
|
-
const serializeTransaction = transaction => {
|
|
64
|
-
if (isVersionedTransaction(transaction)) {
|
|
65
|
-
return crypto.base58.encode(transaction.serialize());
|
|
66
|
-
} else {
|
|
67
|
-
return crypto.base58.encode(transaction.serialize({
|
|
68
|
-
requireAllSignatures: false,
|
|
69
|
-
verifySignatures: false
|
|
70
|
-
}));
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
const deserializeTransaction = transaction => {
|
|
74
|
-
const bytes = crypto.base58.decode(transaction);
|
|
75
|
-
try {
|
|
76
|
-
return web3_js.VersionedTransaction.deserialize(bytes);
|
|
77
|
-
} catch {
|
|
78
|
-
return web3_js.Transaction.from(bytes);
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
const txToHumanJSON = tx => {
|
|
82
|
-
if (typeof tx === "string") tx = deserializeTransaction(tx);
|
|
83
|
-
return isVersionedTransaction(tx) ? versionedTxToJSON(tx) : legacyTxToJSON(tx);
|
|
84
|
-
};
|
|
85
|
-
const legacyTxToJSON = tx => {
|
|
86
|
-
return {
|
|
87
|
-
type: "legacy",
|
|
88
|
-
signatures: tx.signatures.map(s => s.signature ? crypto.base58.encode(s.signature) : null),
|
|
89
|
-
feePayer: tx.feePayer?.toBase58() ?? null,
|
|
90
|
-
recentBlockhash: tx.recentBlockhash ?? null,
|
|
91
|
-
instructions: tx.instructions.map(ix => ({
|
|
92
|
-
programId: ix.programId.toBase58(),
|
|
93
|
-
accounts: ix.keys.map(k => ({
|
|
94
|
-
pubkey: k.pubkey.toBase58(),
|
|
95
|
-
isSigner: k.isSigner,
|
|
96
|
-
isWritable: k.isWritable
|
|
97
|
-
})),
|
|
98
|
-
data: crypto.base58.encode(ix.data)
|
|
99
|
-
}))
|
|
100
|
-
};
|
|
101
|
-
};
|
|
102
|
-
const versionedTxToJSON = tx => {
|
|
103
|
-
const msg = tx.message;
|
|
104
|
-
|
|
105
|
-
// ⚠️ NOTE: without address lookup table accounts we only have static keys.
|
|
106
|
-
const staticKeys = msg.staticAccountKeys;
|
|
107
|
-
return {
|
|
108
|
-
type: "versioned",
|
|
109
|
-
version: msg.version,
|
|
110
|
-
// usually 0
|
|
111
|
-
signatures: tx.signatures.map(sig => crypto.base58.encode(sig)),
|
|
112
|
-
recentBlockhash: msg.recentBlockhash,
|
|
113
|
-
staticAccountKeys: staticKeys.map(k => k.toBase58()),
|
|
114
|
-
addressTableLookups: msg.addressTableLookups?.map(l => ({
|
|
115
|
-
accountKey: l.accountKey.toBase58(),
|
|
116
|
-
writableIndexes: Array.from(l.writableIndexes),
|
|
117
|
-
readonlyIndexes: Array.from(l.readonlyIndexes)
|
|
118
|
-
})) ?? [],
|
|
119
|
-
instructions: msg.compiledInstructions.map(ix => ({
|
|
120
|
-
programIdIndex: ix.programIdIndex,
|
|
121
|
-
programId: staticKeys[ix.programIdIndex]?.toBase58() ?? null,
|
|
122
|
-
accounts: ix.accountKeyIndexes.map(i => ({
|
|
123
|
-
index: i,
|
|
124
|
-
pubkey: staticKeys[i]?.toBase58() ?? null
|
|
125
|
-
})),
|
|
126
|
-
data: crypto.base58.encode(ix.data)
|
|
127
|
-
}))
|
|
128
|
-
};
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
const getKeypair = secretKey => {
|
|
132
|
-
const publicKey = crypto.getPublicKeyFromSecret(secretKey, "solana");
|
|
133
|
-
const fullScretKey = new Uint8Array([...secretKey, ...publicKey]);
|
|
134
|
-
return web3_js.Keypair.fromSecretKey(fullScretKey);
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
const SOLANA_CHAINS = ["solana:mainnet", "solana:devnet", "solana:testnet", "solana:localnet"];
|
|
138
|
-
const getSolNetworkId = chain => {
|
|
139
|
-
switch (chain) {
|
|
140
|
-
case "solana:mainnet":
|
|
141
|
-
return "solana-mainnet";
|
|
142
|
-
case "solana:devnet":
|
|
143
|
-
return "solana-devnet";
|
|
144
|
-
case "solana:testnet":
|
|
145
|
-
return "solana-testnet";
|
|
146
|
-
case "solana:localnet":
|
|
147
|
-
return "solana-localnet";
|
|
148
|
-
default:
|
|
149
|
-
throw new Error(`Unknown Solana chain: ${chain}`);
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
exports.SOLANA_CHAINS = SOLANA_CHAINS;
|
|
154
|
-
exports.deserializeTransaction = deserializeTransaction;
|
|
155
|
-
exports.getKeypair = getKeypair;
|
|
156
|
-
exports.getSolNetworkId = getSolNetworkId;
|
|
157
|
-
exports.isVersionedTransaction = isVersionedTransaction;
|
|
158
|
-
exports.parseTransactionInfo = parseTransactionInfo;
|
|
159
|
-
exports.serializeTransaction = serializeTransaction;
|
|
160
|
-
exports.solInstructionFromJson = solInstructionFromJson;
|
|
161
|
-
exports.solInstructionToJson = solInstructionToJson;
|
|
162
|
-
exports.txToHumanJSON = txToHumanJSON;
|
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var web3_js = require('@solana/web3.js');
|
|
4
|
-
var crypto = require('@talismn/crypto');
|
|
5
|
-
|
|
6
|
-
const isVersionedTransaction = transaction => {
|
|
7
|
-
return "version" in transaction;
|
|
8
|
-
};
|
|
9
|
-
const parseTransactionInfo = tx => {
|
|
10
|
-
if (isVersionedTransaction(tx)) {
|
|
11
|
-
const recentBlockhash = tx.message.recentBlockhash;
|
|
12
|
-
const requiredSigners = tx.message.staticAccountKeys.filter((_, index) => tx.message.isAccountSigner(index));
|
|
13
|
-
const address = requiredSigners.length === 1 ? requiredSigners[0].toBase58() : undefined;
|
|
14
|
-
const sigBytes = tx.signatures.length ? tx.signatures[0] : null;
|
|
15
|
-
|
|
16
|
-
// signature might be an array of zeros, signature needs to be verified manually
|
|
17
|
-
const signature = sigBytes && address && crypto.ed25519.verify(sigBytes, tx.message.serialize(), crypto.base58.decode(address)) ? crypto.base58.encode(sigBytes) : null;
|
|
18
|
-
return {
|
|
19
|
-
recentBlockhash,
|
|
20
|
-
address,
|
|
21
|
-
signature
|
|
22
|
-
};
|
|
23
|
-
} else {
|
|
24
|
-
const recentBlockhash = tx.recentBlockhash;
|
|
25
|
-
const address = tx.feePayer ? tx.feePayer.toBase58() : undefined;
|
|
26
|
-
const signature = tx.verifySignatures() ? crypto.base58.encode(tx.signature) : null;
|
|
27
|
-
return {
|
|
28
|
-
recentBlockhash,
|
|
29
|
-
address,
|
|
30
|
-
signature
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
// Serialize TransactionInstruction to JSON
|
|
36
|
-
const solInstructionToJson = instruction => {
|
|
37
|
-
return {
|
|
38
|
-
type: "solana-instruction",
|
|
39
|
-
value: {
|
|
40
|
-
programId: instruction.programId.toString(),
|
|
41
|
-
keys: instruction.keys.map(key => ({
|
|
42
|
-
pubkey: key.pubkey.toString(),
|
|
43
|
-
isSigner: key.isSigner,
|
|
44
|
-
isWritable: key.isWritable
|
|
45
|
-
})),
|
|
46
|
-
data: instruction.data.toString("base64")
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
};
|
|
50
|
-
// Deserialize JSON back to TransactionInstruction
|
|
51
|
-
const solInstructionFromJson = serialized => {
|
|
52
|
-
if (serialized.type !== "solana-instruction") throw new Error("Invalid serialized instruction type");
|
|
53
|
-
return {
|
|
54
|
-
programId: new web3_js.PublicKey(serialized.value.programId),
|
|
55
|
-
keys: serialized.value.keys.map(key => ({
|
|
56
|
-
pubkey: new web3_js.PublicKey(key.pubkey),
|
|
57
|
-
isSigner: key.isSigner,
|
|
58
|
-
isWritable: key.isWritable
|
|
59
|
-
})),
|
|
60
|
-
data: Buffer.from(serialized.value.data, "base64")
|
|
61
|
-
};
|
|
62
|
-
};
|
|
63
|
-
const serializeTransaction = transaction => {
|
|
64
|
-
if (isVersionedTransaction(transaction)) {
|
|
65
|
-
return crypto.base58.encode(transaction.serialize());
|
|
66
|
-
} else {
|
|
67
|
-
return crypto.base58.encode(transaction.serialize({
|
|
68
|
-
requireAllSignatures: false,
|
|
69
|
-
verifySignatures: false
|
|
70
|
-
}));
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
const deserializeTransaction = transaction => {
|
|
74
|
-
const bytes = crypto.base58.decode(transaction);
|
|
75
|
-
try {
|
|
76
|
-
return web3_js.VersionedTransaction.deserialize(bytes);
|
|
77
|
-
} catch {
|
|
78
|
-
return web3_js.Transaction.from(bytes);
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
const txToHumanJSON = tx => {
|
|
82
|
-
if (typeof tx === "string") tx = deserializeTransaction(tx);
|
|
83
|
-
return isVersionedTransaction(tx) ? versionedTxToJSON(tx) : legacyTxToJSON(tx);
|
|
84
|
-
};
|
|
85
|
-
const legacyTxToJSON = tx => {
|
|
86
|
-
return {
|
|
87
|
-
type: "legacy",
|
|
88
|
-
signatures: tx.signatures.map(s => s.signature ? crypto.base58.encode(s.signature) : null),
|
|
89
|
-
feePayer: tx.feePayer?.toBase58() ?? null,
|
|
90
|
-
recentBlockhash: tx.recentBlockhash ?? null,
|
|
91
|
-
instructions: tx.instructions.map(ix => ({
|
|
92
|
-
programId: ix.programId.toBase58(),
|
|
93
|
-
accounts: ix.keys.map(k => ({
|
|
94
|
-
pubkey: k.pubkey.toBase58(),
|
|
95
|
-
isSigner: k.isSigner,
|
|
96
|
-
isWritable: k.isWritable
|
|
97
|
-
})),
|
|
98
|
-
data: crypto.base58.encode(ix.data)
|
|
99
|
-
}))
|
|
100
|
-
};
|
|
101
|
-
};
|
|
102
|
-
const versionedTxToJSON = tx => {
|
|
103
|
-
const msg = tx.message;
|
|
104
|
-
|
|
105
|
-
// ⚠️ NOTE: without address lookup table accounts we only have static keys.
|
|
106
|
-
const staticKeys = msg.staticAccountKeys;
|
|
107
|
-
return {
|
|
108
|
-
type: "versioned",
|
|
109
|
-
version: msg.version,
|
|
110
|
-
// usually 0
|
|
111
|
-
signatures: tx.signatures.map(sig => crypto.base58.encode(sig)),
|
|
112
|
-
recentBlockhash: msg.recentBlockhash,
|
|
113
|
-
staticAccountKeys: staticKeys.map(k => k.toBase58()),
|
|
114
|
-
addressTableLookups: msg.addressTableLookups?.map(l => ({
|
|
115
|
-
accountKey: l.accountKey.toBase58(),
|
|
116
|
-
writableIndexes: Array.from(l.writableIndexes),
|
|
117
|
-
readonlyIndexes: Array.from(l.readonlyIndexes)
|
|
118
|
-
})) ?? [],
|
|
119
|
-
instructions: msg.compiledInstructions.map(ix => ({
|
|
120
|
-
programIdIndex: ix.programIdIndex,
|
|
121
|
-
programId: staticKeys[ix.programIdIndex]?.toBase58() ?? null,
|
|
122
|
-
accounts: ix.accountKeyIndexes.map(i => ({
|
|
123
|
-
index: i,
|
|
124
|
-
pubkey: staticKeys[i]?.toBase58() ?? null
|
|
125
|
-
})),
|
|
126
|
-
data: crypto.base58.encode(ix.data)
|
|
127
|
-
}))
|
|
128
|
-
};
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
const getKeypair = secretKey => {
|
|
132
|
-
const publicKey = crypto.getPublicKeyFromSecret(secretKey, "solana");
|
|
133
|
-
const fullScretKey = new Uint8Array([...secretKey, ...publicKey]);
|
|
134
|
-
return web3_js.Keypair.fromSecretKey(fullScretKey);
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
const SOLANA_CHAINS = ["solana:mainnet", "solana:devnet", "solana:testnet", "solana:localnet"];
|
|
138
|
-
const getSolNetworkId = chain => {
|
|
139
|
-
switch (chain) {
|
|
140
|
-
case "solana:mainnet":
|
|
141
|
-
return "solana-mainnet";
|
|
142
|
-
case "solana:devnet":
|
|
143
|
-
return "solana-devnet";
|
|
144
|
-
case "solana:testnet":
|
|
145
|
-
return "solana-testnet";
|
|
146
|
-
case "solana:localnet":
|
|
147
|
-
return "solana-localnet";
|
|
148
|
-
default:
|
|
149
|
-
throw new Error(`Unknown Solana chain: ${chain}`);
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
exports.SOLANA_CHAINS = SOLANA_CHAINS;
|
|
154
|
-
exports.deserializeTransaction = deserializeTransaction;
|
|
155
|
-
exports.getKeypair = getKeypair;
|
|
156
|
-
exports.getSolNetworkId = getSolNetworkId;
|
|
157
|
-
exports.isVersionedTransaction = isVersionedTransaction;
|
|
158
|
-
exports.parseTransactionInfo = parseTransactionInfo;
|
|
159
|
-
exports.serializeTransaction = serializeTransaction;
|
|
160
|
-
exports.solInstructionFromJson = solInstructionFromJson;
|
|
161
|
-
exports.solInstructionToJson = solInstructionToJson;
|
|
162
|
-
exports.txToHumanJSON = txToHumanJSON;
|