@talismn/solana 0.0.10 → 1.0.1

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.mjs CHANGED
@@ -1,167 +1,194 @@
1
- // src/utils/chains.ts
2
- var SOLANA_CHAINS = [
3
- "solana:mainnet",
4
- "solana:devnet",
5
- "solana:testnet",
6
- "solana:localnet"
1
+ import { address, appendTransactionMessageInstructions, compileTransaction, createTransactionMessage, getBase64Decoder, getCompiledTransactionMessageDecoder, getCompiledTransactionMessageEncoder, getTransactionDecoder, getTransactionEncoder, pipe, setTransactionMessageFeePayer, setTransactionMessageLifetimeUsingBlockhash } from "@solana/kit";
2
+ import { base58, ed25519, getPublicKeyFromSecret } from "@talismn/crypto";
3
+ //#region src/utils/chains.ts
4
+ const SOLANA_CHAINS = [
5
+ "solana:mainnet",
6
+ "solana:devnet",
7
+ "solana:testnet",
8
+ "solana:localnet"
7
9
  ];
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
- }
10
+ const getSolNetworkId = (chain) => {
11
+ switch (chain) {
12
+ case "solana:mainnet": return "solana-mainnet";
13
+ case "solana:devnet": return "solana-devnet";
14
+ case "solana:testnet": return "solana-testnet";
15
+ case "solana:localnet": return "solana-localnet";
16
+ default: throw new Error(`Unknown Solana chain: ${chain}`);
17
+ }
21
18
  };
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";
30
-
31
- // src/utils/transaction.ts
32
- import { base58, ed25519 } from "@talismn/crypto";
33
- var isVersionedTransaction = (transaction) => {
34
- return "version" in transaction;
19
+ //#endregion
20
+ //#region src/utils/offchainMessage.ts
21
+ const SIGNING_DOMAIN = new Uint8Array([255, ...Array.from("solana offchain", (c) => c.charCodeAt(0))]);
22
+ const APPLICATION_DOMAIN_LENGTH = 32;
23
+ const PUBLIC_KEY_LENGTH = 32;
24
+ const HEADER_LENGTH = SIGNING_DOMAIN.length + 1 + APPLICATION_DOMAIN_LENGTH + 1 + 1 + PUBLIC_KEY_LENGTH + 2;
25
+ /** Hardware wallet compatible v0 messages are capped at 1232 bytes total, header included */
26
+ const MAX_MESSAGE_LENGTH = 1232 - HEADER_LENGTH;
27
+ const FORMAT_RESTRICTED_ASCII = 0;
28
+ const FORMAT_LIMITED_UTF8 = 1;
29
+ const getMessageFormat = (message) => {
30
+ if (message.every((byte) => byte >= 32 && byte <= 126)) return FORMAT_RESTRICTED_ASCII;
31
+ try {
32
+ new TextDecoder("utf-8", { fatal: true }).decode(message);
33
+ return FORMAT_LIMITED_UTF8;
34
+ } catch {
35
+ return null;
36
+ }
35
37
  };
36
- var parseTransactionInfo = (tx) => {
37
- if (isVersionedTransaction(tx)) {
38
- const recentBlockhash = tx.message.recentBlockhash;
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;
43
- const sigBytes = tx.signatures.length ? tx.signatures[0] : null;
44
- const signature = sigBytes && address && ed25519.verify(sigBytes, tx.message.serialize(), base58.decode(address)) ? base58.encode(sigBytes) : null;
45
- return { recentBlockhash, address, signature };
46
- } else {
47
- const recentBlockhash = tx.recentBlockhash;
48
- const address = tx.feePayer ? tx.feePayer.toBase58() : void 0;
49
- const signature = tx.verifySignatures() ? base58.encode(tx.signature) : null;
50
- return { recentBlockhash, address, signature };
51
- }
38
+ /**
39
+ * Wraps a raw message in the off-chain message envelope that hardware wallets sign.
40
+ * Returns `null` if the message cannot be wrapped (binary content, empty, or too long).
41
+ */
42
+ const serializeOffchainMessage = (message, signerPublicKey) => {
43
+ if (message.length === 0 || message.length > MAX_MESSAGE_LENGTH) return null;
44
+ if (signerPublicKey.length !== PUBLIC_KEY_LENGTH) return null;
45
+ const format = getMessageFormat(message);
46
+ if (format === null) return null;
47
+ const envelope = new Uint8Array(HEADER_LENGTH + message.length);
48
+ let offset = 0;
49
+ envelope.set(SIGNING_DOMAIN, offset);
50
+ offset += SIGNING_DOMAIN.length;
51
+ envelope[offset++] = 0;
52
+ offset += APPLICATION_DOMAIN_LENGTH;
53
+ envelope[offset++] = format;
54
+ envelope[offset++] = 1;
55
+ envelope.set(signerPublicKey, offset);
56
+ offset += PUBLIC_KEY_LENGTH;
57
+ envelope[offset++] = message.length & 255;
58
+ envelope[offset++] = message.length >> 8;
59
+ envelope.set(message, offset);
60
+ return envelope;
52
61
  };
53
-
54
- // src/utils/serialization.ts
55
- var solInstructionToJson = (instruction) => {
56
- return {
57
- type: "solana-instruction",
58
- value: {
59
- programId: instruction.programId.toString(),
60
- keys: instruction.keys.map((key) => ({
61
- pubkey: key.pubkey.toString(),
62
- isSigner: key.isSigner,
63
- isWritable: key.isWritable
64
- })),
65
- data: instruction.data.toString("base64")
66
- }
67
- };
62
+ //#endregion
63
+ //#region src/utils/serialization.ts
64
+ const transactionFromBytes = (bytes) => getTransactionDecoder().decode(bytes);
65
+ const transactionToBytes = (tx) => new Uint8Array(getTransactionEncoder().encode(tx));
66
+ /** base58 of the wire-format transaction — both legacy and v0, wire-compatible with web3.js */
67
+ const serializeTransaction = (tx) => base58.encode(transactionToBytes(tx));
68
+ const deserializeTransaction = (transaction) => transactionFromBytes(base58.decode(transaction));
69
+ /** decoded compiled message — legacy and v0 wire formats are handled transparently */
70
+ const getCompiledMessage = (tx) => getCompiledTransactionMessageDecoder().decode(tx.messageBytes);
71
+ /**
72
+ * Whether the bytes parse as a complete compiled transaction message (legacy or v0).
73
+ * Wallets must refuse to sign such a payload as a "message": Solana software accounts sign raw
74
+ * message bytes with no domain separator, so the resulting ed25519 signature would double as a
75
+ * valid transaction signature.
76
+ */
77
+ const isCompiledTransactionMessage = (bytes) => {
78
+ try {
79
+ const [, offset] = getCompiledTransactionMessageDecoder().read(bytes, 0);
80
+ return offset === bytes.length;
81
+ } catch {
82
+ return false;
83
+ }
68
84
  };
69
- var solInstructionFromJson = (serialized) => {
70
- if (serialized.type !== "solana-instruction")
71
- throw new Error("Invalid serialized instruction type");
72
- return {
73
- programId: new PublicKey(serialized.value.programId),
74
- keys: serialized.value.keys.map((key) => ({
75
- pubkey: new PublicKey(key.pubkey),
76
- isSigner: key.isSigner,
77
- isWritable: key.isWritable
78
- })),
79
- data: Buffer.from(serialized.value.data, "base64")
80
- };
85
+ /** base64 of the compiled message bytes, the format `getFeeForMessage` expects */
86
+ const getMessageBase64 = (tx) => getBase64Decoder().decode(tx.messageBytes);
87
+ const buildUnsignedTransaction = ({ feePayer, blockhash, lastValidBlockHeight, instructions, version = "legacy" }) => pipe(createTransactionMessage({ version }), (m) => setTransactionMessageFeePayer(address(feePayer), m), (m) => setTransactionMessageLifetimeUsingBlockhash({
88
+ blockhash,
89
+ lastValidBlockHeight
90
+ }, m), (m) => appendTransactionMessageInstructions(instructions, m), compileTransaction);
91
+ /**
92
+ * Returns a copy of the transaction with its lifetime token (recent blockhash) replaced,
93
+ * re-encoding the compiled message. Existing signatures are reset to null — changing the
94
+ * blockhash invalidates them.
95
+ */
96
+ const setTransactionBlockhash = (tx, blockhash) => {
97
+ const compiled = getCompiledTransactionMessageDecoder().decode(tx.messageBytes);
98
+ const messageBytes = getCompiledTransactionMessageEncoder().encode({
99
+ ...compiled,
100
+ lifetimeToken: blockhash
101
+ });
102
+ return Object.freeze({
103
+ messageBytes,
104
+ signatures: Object.freeze(Object.fromEntries(Object.keys(tx.signatures).map((address) => [address, null])))
105
+ });
81
106
  };
82
- var serializeTransaction = (transaction) => {
83
- if (isVersionedTransaction(transaction)) {
84
- return base582.encode(transaction.serialize());
85
- } else {
86
- return base582.encode(
87
- transaction.serialize({ requireAllSignatures: false, verifySignatures: false })
88
- );
89
- }
107
+ const txToHumanJSON = (tx) => {
108
+ if (typeof tx === "string") tx = deserializeTransaction(tx);
109
+ const message = getCompiledMessage(tx);
110
+ const { header, staticAccounts } = message;
111
+ const isSigner = (index) => index < header.numSignerAccounts;
112
+ const isWritable = (index) => index < header.numSignerAccounts ? index < header.numSignerAccounts - header.numReadonlySignerAccounts : index < staticAccounts.length - header.numReadonlyNonSignerAccounts;
113
+ return {
114
+ version: message.version,
115
+ signatures: Object.values(tx.signatures).map((sig) => sig ? base58.encode(sig) : null),
116
+ feePayer: staticAccounts[0] ?? null,
117
+ recentBlockhash: "lifetimeToken" in message ? message.lifetimeToken : null,
118
+ staticAccountKeys: staticAccounts,
119
+ addressTableLookups: ("addressTableLookups" in message ? message.addressTableLookups : void 0)?.map((l) => ({
120
+ accountKey: l.lookupTableAddress,
121
+ writableIndexes: Array.from(l.writableIndexes),
122
+ readonlyIndexes: Array.from(l.readonlyIndexes)
123
+ })) ?? [],
124
+ instructions: ("instructions" in message ? message.instructions : []).map((ix) => ({
125
+ programIdIndex: ix.programAddressIndex,
126
+ programId: staticAccounts[ix.programAddressIndex] ?? null,
127
+ accounts: (ix.accountIndices ?? []).map((i) => ({
128
+ index: i,
129
+ pubkey: staticAccounts[i] ?? null,
130
+ isSigner: isSigner(i),
131
+ isWritable: isWritable(i)
132
+ })),
133
+ data: base58.encode(ix.data ?? /* @__PURE__ */ new Uint8Array())
134
+ }))
135
+ };
90
136
  };
91
- var deserializeTransaction = (transaction) => {
92
- const bytes = base582.decode(transaction);
93
- try {
94
- return VersionedTransaction.deserialize(bytes);
95
- } catch {
96
- return Transaction.from(bytes);
97
- }
137
+ //#endregion
138
+ //#region src/utils/signing.ts
139
+ /**
140
+ * Returns a copy of the transaction with `signature` attached for `address`.
141
+ * Throws if `address` is not a required signer of the transaction (the signatures
142
+ * map is keyed in wire order at decode time — adding a key would corrupt re-encoding).
143
+ */
144
+ const attachTransactionSignature = (tx, address, signature) => {
145
+ if (!(address in tx.signatures)) throw new Error(`Address ${address} is not a signer of this transaction`);
146
+ return Object.freeze({
147
+ ...tx,
148
+ signatures: Object.freeze({
149
+ ...tx.signatures,
150
+ [address]: signature
151
+ })
152
+ });
98
153
  };
99
- var txToHumanJSON = (tx) => {
100
- if (typeof tx === "string") tx = deserializeTransaction(tx);
101
- return isVersionedTransaction(tx) ? versionedTxToJSON(tx) : legacyTxToJSON(tx);
154
+ /**
155
+ * Returns the signature attached for `address`, verified against the transaction's message
156
+ * bytes; null when missing, all-zeros, or invalid. Unlike `parseTransactionInfo`, this checks
157
+ * a specific signer's slot, so it works on transactions with co-signers.
158
+ */
159
+ const getVerifiedTransactionSignature = (tx, address) => {
160
+ const signature = tx.signatures[address];
161
+ return signature && ed25519.verify(signature, tx.messageBytes, base58.decode(address)) ? signature : null;
102
162
  };
103
- var legacyTxToJSON = (tx) => {
104
- return {
105
- type: "legacy",
106
- signatures: tx.signatures.map((s) => s.signature ? base582.encode(s.signature) : null),
107
- feePayer: tx.feePayer?.toBase58() ?? null,
108
- recentBlockhash: tx.recentBlockhash ?? null,
109
- instructions: tx.instructions.map((ix) => ({
110
- programId: ix.programId.toBase58(),
111
- accounts: ix.keys.map((k) => ({
112
- pubkey: k.pubkey.toBase58(),
113
- isSigner: k.isSigner,
114
- isWritable: k.isWritable
115
- })),
116
- data: base582.encode(ix.data)
117
- }))
118
- };
163
+ /**
164
+ * Signs the transaction's message bytes with the given ed25519 secret key and
165
+ * attaches the signature. Signing happens with @noble/curves (via @talismn/crypto),
166
+ * not WebCrypto — Ed25519 subtle crypto is too recent for the extension's support matrix.
167
+ */
168
+ const signTransactionWithSecretKey = (tx, secretKey, expectedAddress) => {
169
+ const address = base58.encode(getPublicKeyFromSecret(secretKey, "solana"));
170
+ if (expectedAddress && address !== expectedAddress) throw new Error("Address mismatch");
171
+ const signature = ed25519.sign(tx.messageBytes, secretKey);
172
+ return attachTransactionSignature(tx, address, signature);
119
173
  };
120
- var versionedTxToJSON = (tx) => {
121
- const msg = tx.message;
122
- const staticKeys = msg.staticAccountKeys;
123
- return {
124
- type: "versioned",
125
- version: msg.version,
126
- // usually 0
127
- signatures: tx.signatures.map((sig) => base582.encode(sig)),
128
- recentBlockhash: msg.recentBlockhash,
129
- staticAccountKeys: staticKeys.map((k) => k.toBase58()),
130
- addressTableLookups: msg.addressTableLookups?.map((l) => ({
131
- accountKey: l.accountKey.toBase58(),
132
- writableIndexes: Array.from(l.writableIndexes),
133
- readonlyIndexes: Array.from(l.readonlyIndexes)
134
- })) ?? [],
135
- instructions: msg.compiledInstructions.map((ix) => ({
136
- programIdIndex: ix.programIdIndex,
137
- programId: staticKeys[ix.programIdIndex]?.toBase58() ?? null,
138
- accounts: ix.accountKeyIndexes.map((i) => ({
139
- index: i,
140
- pubkey: staticKeys[i]?.toBase58() ?? null
141
- })),
142
- data: base582.encode(ix.data)
143
- }))
144
- };
174
+ //#endregion
175
+ //#region src/utils/transaction.ts
176
+ const parseTransactionInfo = (tx) => {
177
+ const message = getCompiledMessage(tx);
178
+ const signerAddresses = Object.keys(tx.signatures);
179
+ const feePayer = message.staticAccounts[0];
180
+ const address = message.version === "legacy" ? signerAddresses[0] : signerAddresses.length === 1 ? signerAddresses[0] : void 0;
181
+ const sigBytes = getVerifiedTransactionSignature(tx, feePayer);
182
+ return {
183
+ version: message.version,
184
+ recentBlockhash: "lifetimeToken" in message ? message.lifetimeToken : "",
185
+ feePayer,
186
+ signerAddresses,
187
+ address,
188
+ signature: sigBytes ? base58.encode(sigBytes) : null
189
+ };
145
190
  };
191
+ //#endregion
192
+ export { SOLANA_CHAINS, attachTransactionSignature, buildUnsignedTransaction, deserializeTransaction, getCompiledMessage, getMessageBase64, getSolNetworkId, getVerifiedTransactionSignature, isCompiledTransactionMessage, parseTransactionInfo, serializeOffchainMessage, serializeTransaction, setTransactionBlockhash, signTransactionWithSecretKey, transactionFromBytes, transactionToBytes, txToHumanJSON };
146
193
 
147
- // src/utils/signing.ts
148
- import { Keypair } from "@solana/web3.js";
149
- import { getPublicKeyFromSecret } from "@talismn/crypto";
150
- var getKeypair = (secretKey) => {
151
- const publicKey = getPublicKeyFromSecret(secretKey, "solana");
152
- const fullScretKey = new Uint8Array([...secretKey, ...publicKey]);
153
- return Keypair.fromSecretKey(fullScretKey);
154
- };
155
- export {
156
- SOLANA_CHAINS,
157
- deserializeTransaction,
158
- getKeypair,
159
- getSolNetworkId,
160
- isVersionedTransaction,
161
- parseTransactionInfo,
162
- serializeTransaction,
163
- solInstructionFromJson,
164
- solInstructionToJson,
165
- txToHumanJSON
166
- };
167
194
  //# sourceMappingURL=index.mjs.map
@@ -1 +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"]}
1
+ {"version":3,"file":"index.mjs","names":["solAddress"],"sources":["../src/utils/chains.ts","../src/utils/offchainMessage.ts","../src/utils/serialization.ts","../src/utils/signing.ts","../src/utils/transaction.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","// Solana off-chain message envelope (v0), as specified by Anza and enforced by the Ledger app\n// (1.8.0+): https://github.com/anza-xyz/agave/blob/master/docs/src/proposals/off-chain-message-signing.md\n//\n// signing domain \"\\xffsolana offchain\" (16 bytes) || header version (1 byte, 0) ||\n// application domain (32 bytes, zeros = not provided) || message format (1 byte) ||\n// signer count (1 byte) || signers (32 bytes each) || message length (2 bytes LE) || message\n//\n// Hardware wallets refuse to sign arbitrary raw bytes - only transactions and messages wrapped\n// in this envelope, and the derivation path's public key must appear in the signers list.\n// Note this is NOT the format implemented by @solana/offchain-messages (kit), whose codec\n// details differ from what the Ledger app validates.\n\nconst SIGNING_DOMAIN = new Uint8Array([\n 0xff,\n ...Array.from(\"solana offchain\", (c) => c.charCodeAt(0)),\n])\n\nconst APPLICATION_DOMAIN_LENGTH = 32\nconst PUBLIC_KEY_LENGTH = 32\n\n// domain + version + application domain + format + signer count + one signer + length\nconst HEADER_LENGTH =\n SIGNING_DOMAIN.length + 1 + APPLICATION_DOMAIN_LENGTH + 1 + 1 + PUBLIC_KEY_LENGTH + 2\n\n/** Hardware wallet compatible v0 messages are capped at 1232 bytes total, header included */\nconst MAX_MESSAGE_LENGTH = 1232 - HEADER_LENGTH\n\nconst FORMAT_RESTRICTED_ASCII = 0\nconst FORMAT_LIMITED_UTF8 = 1\n\nconst getMessageFormat = (message: Uint8Array): number | null => {\n if (message.every((byte) => byte >= 0x20 && byte <= 0x7e)) return FORMAT_RESTRICTED_ASCII\n\n try {\n new TextDecoder(\"utf-8\", { fatal: true }).decode(message)\n return FORMAT_LIMITED_UTF8\n } catch {\n return null // binary content cannot be wrapped\n }\n}\n\n/**\n * Wraps a raw message in the off-chain message envelope that hardware wallets sign.\n * Returns `null` if the message cannot be wrapped (binary content, empty, or too long).\n */\nexport const serializeOffchainMessage = (\n message: Uint8Array,\n signerPublicKey: Uint8Array\n): Uint8Array | null => {\n if (message.length === 0 || message.length > MAX_MESSAGE_LENGTH) return null\n if (signerPublicKey.length !== PUBLIC_KEY_LENGTH) return null\n\n const format = getMessageFormat(message)\n if (format === null) return null\n\n const envelope = new Uint8Array(HEADER_LENGTH + message.length)\n let offset = 0\n\n envelope.set(SIGNING_DOMAIN, offset)\n offset += SIGNING_DOMAIN.length\n\n envelope[offset++] = 0 // header version\n\n offset += APPLICATION_DOMAIN_LENGTH // application domain: zeros = not provided\n\n envelope[offset++] = format\n envelope[offset++] = 1 // signer count\n\n envelope.set(signerPublicKey, offset)\n offset += PUBLIC_KEY_LENGTH\n\n envelope[offset++] = message.length & 0xff\n envelope[offset++] = message.length >> 8\n\n envelope.set(message, offset)\n\n return envelope\n}\n","import type {\n Blockhash,\n Instruction,\n SignaturesMap,\n TransactionMessageBytes,\n TransactionMessageBytesBase64,\n} from \"@solana/kit\"\nimport {\n appendTransactionMessageInstructions,\n compileTransaction,\n createTransactionMessage,\n getBase64Decoder,\n getCompiledTransactionMessageDecoder,\n getCompiledTransactionMessageEncoder,\n getTransactionDecoder,\n getTransactionEncoder,\n pipe,\n setTransactionMessageFeePayer,\n setTransactionMessageLifetimeUsingBlockhash,\n address as solAddress,\n} from \"@solana/kit\"\nimport { base58 } from \"@talismn/crypto\"\n\nimport type { SolTransaction } from \"./transaction\"\n\nexport const transactionFromBytes = (bytes: Uint8Array): SolTransaction =>\n getTransactionDecoder().decode(bytes)\n\nexport const transactionToBytes = (tx: SolTransaction): Uint8Array =>\n new Uint8Array(getTransactionEncoder().encode(tx))\n\n/** base58 of the wire-format transaction — both legacy and v0, wire-compatible with web3.js */\nexport const serializeTransaction = (tx: SolTransaction): string =>\n base58.encode(transactionToBytes(tx))\n\nexport const deserializeTransaction = (transaction: string): SolTransaction =>\n transactionFromBytes(base58.decode(transaction))\n\n/** decoded compiled message — legacy and v0 wire formats are handled transparently */\nexport const getCompiledMessage = (tx: SolTransaction) =>\n getCompiledTransactionMessageDecoder().decode(tx.messageBytes)\n\n/**\n * Whether the bytes parse as a complete compiled transaction message (legacy or v0).\n * Wallets must refuse to sign such a payload as a \"message\": Solana software accounts sign raw\n * message bytes with no domain separator, so the resulting ed25519 signature would double as a\n * valid transaction signature.\n */\nexport const isCompiledTransactionMessage = (bytes: Uint8Array): boolean => {\n try {\n const [, offset] = getCompiledTransactionMessageDecoder().read(bytes, 0)\n return offset === bytes.length\n } catch {\n return false\n }\n}\n\n/** base64 of the compiled message bytes, the format `getFeeForMessage` expects */\nexport const getMessageBase64 = (tx: SolTransaction): TransactionMessageBytesBase64 =>\n getBase64Decoder().decode(tx.messageBytes) as TransactionMessageBytesBase64\n\nexport const buildUnsignedTransaction = ({\n feePayer,\n blockhash,\n lastValidBlockHeight,\n instructions,\n version = \"legacy\",\n}: {\n feePayer: string\n blockhash: string\n lastValidBlockHeight: bigint\n instructions: Instruction[]\n version?: \"legacy\" | 0\n}): SolTransaction =>\n pipe(\n createTransactionMessage({ version }),\n (m) => setTransactionMessageFeePayer(solAddress(feePayer), m),\n (m) =>\n setTransactionMessageLifetimeUsingBlockhash(\n { blockhash: blockhash as Blockhash, lastValidBlockHeight },\n m\n ),\n (m) => appendTransactionMessageInstructions(instructions, m),\n compileTransaction\n )\n\n/**\n * Returns a copy of the transaction with its lifetime token (recent blockhash) replaced,\n * re-encoding the compiled message. Existing signatures are reset to null — changing the\n * blockhash invalidates them.\n */\nexport const setTransactionBlockhash = (tx: SolTransaction, blockhash: string): SolTransaction => {\n const compiled = getCompiledTransactionMessageDecoder().decode(tx.messageBytes)\n const messageBytes = getCompiledTransactionMessageEncoder().encode({\n ...compiled,\n lifetimeToken: blockhash,\n }) as TransactionMessageBytes\n\n return Object.freeze({\n messageBytes,\n signatures: Object.freeze(\n Object.fromEntries(Object.keys(tx.signatures).map((address) => [address, null]))\n ) as SignaturesMap,\n })\n}\n\nexport const txToHumanJSON = (tx: string | SolTransaction) => {\n if (typeof tx === \"string\") tx = deserializeTransaction(tx)\n const message = getCompiledMessage(tx)\n const { header, staticAccounts } = message\n\n // standard account ordering: writable signers, readonly signers, writable non-signers, readonly non-signers\n const isSigner = (index: number) => index < header.numSignerAccounts\n const isWritable = (index: number) =>\n index < header.numSignerAccounts\n ? index < header.numSignerAccounts - header.numReadonlySignerAccounts\n : index < staticAccounts.length - header.numReadonlyNonSignerAccounts\n\n return {\n version: message.version,\n signatures: Object.values(tx.signatures).map((sig) => (sig ? base58.encode(sig) : null)),\n feePayer: staticAccounts[0] ?? null,\n recentBlockhash: \"lifetimeToken\" in message ? message.lifetimeToken : null,\n staticAccountKeys: staticAccounts as readonly string[],\n // ⚠️ NOTE: without address lookup table accounts we only have static keys.\n addressTableLookups:\n (\"addressTableLookups\" in message ? message.addressTableLookups : undefined)?.map((l) => ({\n accountKey: l.lookupTableAddress as string,\n writableIndexes: Array.from(l.writableIndexes),\n readonlyIndexes: Array.from(l.readonlyIndexes),\n })) ?? [],\n instructions: (\"instructions\" in message ? message.instructions : []).map((ix) => ({\n programIdIndex: ix.programAddressIndex,\n programId: staticAccounts[ix.programAddressIndex] ?? null,\n accounts: (ix.accountIndices ?? []).map((i) => ({\n index: i,\n pubkey: staticAccounts[i] ?? null,\n isSigner: isSigner(i),\n isWritable: isWritable(i),\n })),\n data: base58.encode((ix.data as Uint8Array | undefined) ?? new Uint8Array()),\n })),\n }\n}\n","import type { SignatureBytes } from \"@solana/kit\"\nimport { base58, ed25519, getPublicKeyFromSecret } from \"@talismn/crypto\"\n\nimport type { SolTransaction } from \"./transaction\"\n\n/**\n * Returns a copy of the transaction with `signature` attached for `address`.\n * Throws if `address` is not a required signer of the transaction (the signatures\n * map is keyed in wire order at decode time — adding a key would corrupt re-encoding).\n */\nexport const attachTransactionSignature = (\n tx: SolTransaction,\n address: string,\n signature: Uint8Array\n): SolTransaction => {\n if (!(address in tx.signatures))\n throw new Error(`Address ${address} is not a signer of this transaction`)\n\n return Object.freeze({\n ...tx,\n signatures: Object.freeze({ ...tx.signatures, [address]: signature as SignatureBytes }),\n })\n}\n\n/**\n * Returns the signature attached for `address`, verified against the transaction's message\n * bytes; null when missing, all-zeros, or invalid. Unlike `parseTransactionInfo`, this checks\n * a specific signer's slot, so it works on transactions with co-signers.\n */\nexport const getVerifiedTransactionSignature = (\n tx: SolTransaction,\n address: string\n): Uint8Array | null => {\n const signature = tx.signatures[address as keyof typeof tx.signatures]\n return signature &&\n ed25519.verify(signature, tx.messageBytes as unknown as Uint8Array, base58.decode(address))\n ? signature\n : null\n}\n\n/**\n * Signs the transaction's message bytes with the given ed25519 secret key and\n * attaches the signature. Signing happens with @noble/curves (via @talismn/crypto),\n * not WebCrypto — Ed25519 subtle crypto is too recent for the extension's support matrix.\n */\nexport const signTransactionWithSecretKey = (\n tx: SolTransaction,\n secretKey: Uint8Array,\n expectedAddress?: string\n): SolTransaction => {\n const address = base58.encode(getPublicKeyFromSecret(secretKey, \"solana\"))\n\n if (expectedAddress && address !== expectedAddress) throw new Error(\"Address mismatch\")\n\n const signature = ed25519.sign(tx.messageBytes as unknown as Uint8Array, secretKey)\n\n return attachTransactionSignature(tx, address, signature)\n}\n","import type { Transaction } from \"@solana/kit\"\nimport { base58 } from \"@talismn/crypto\"\n\nimport { getCompiledMessage } from \"./serialization\"\nimport { getVerifiedTransactionSignature } from \"./signing\"\n\n/**\n * A Solana transaction: raw wire message bytes plus a signer-address → signature map.\n * Kit's decoder/encoder handles both legacy and v0 wire formats transparently.\n */\nexport type SolTransaction = Transaction\n\nexport type SolTransactionInfo = {\n version: \"legacy\" | 0 | 1\n /** compiled lifetime token — the recent blockhash (or nonce for durable-nonce transactions) */\n recentBlockhash: string\n /** first static account, the account that pays the transaction fee */\n feePayer: string\n /** all required signer addresses, in wire order */\n signerAddresses: string[]\n /**\n * The account expected to sign in wallet flows.\n * `undefined` when the transaction has several signers (e.g. sponsored/partially-signed\n * dapp transactions) — callers use this to fall back to the dapp-provided address.\n */\n address: string | undefined\n /**\n * canonical (fee payer) base58 transaction signature, verified against the message bytes;\n * null when the fee payer hasn't signed\n */\n signature: string | null\n}\n\nexport const parseTransactionInfo = (tx: SolTransaction): SolTransactionInfo => {\n const message = getCompiledMessage(tx)\n const signerAddresses = Object.keys(tx.signatures)\n const feePayer = message.staticAccounts[0] as string\n\n // Behavior preserved from the web3.js implementation: legacy transactions always\n // resolve to the fee payer, versioned ones only when there is a single signer.\n const address =\n message.version === \"legacy\"\n ? signerAddresses[0]\n : signerAddresses.length === 1\n ? signerAddresses[0]\n : undefined\n\n // the canonical transaction signature is the fee payer's — may be missing or\n // all-zeros, so always verify against the message bytes\n const sigBytes = getVerifiedTransactionSignature(tx, feePayer)\n\n return {\n version: message.version,\n recentBlockhash: \"lifetimeToken\" in message ? message.lifetimeToken : \"\",\n feePayer,\n signerAddresses,\n address,\n signature: sigBytes ? base58.encode(sigBytes) : null,\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@talismn/solana",
3
- "version": "0.0.10",
3
+ "version": "1.0.1",
4
4
  "author": "Talisman",
5
5
  "homepage": "https://talisman.xyz",
6
- "license": "GPL-3.0-or-later",
6
+ "license": "SEE LICENSE IN LICENSE",
7
7
  "publishConfig": {
8
8
  "access": "public"
9
9
  },
@@ -21,12 +21,12 @@
21
21
  "node": ">=20"
22
22
  },
23
23
  "dependencies": {
24
- "@solana/web3.js": "^1.98.2",
25
- "@talismn/crypto": "0.3.5"
24
+ "@solana/kit": "6.10.0",
25
+ "@talismn/crypto": "1.0.1"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^24.5.1",
29
- "typescript": "^6.0.3",
29
+ "typescript": "^7.0.2",
30
30
  "@talismn/tsconfig": "0.0.4"
31
31
  },
32
32
  "types": "./dist/index.d.ts",
@@ -46,7 +46,7 @@
46
46
  "scripts": {
47
47
  "test": "vitest run",
48
48
  "clean": "rm -rf dist .turbo node_modules",
49
- "build": "tsup --silent",
49
+ "build": "tsdown -l error",
50
50
  "typecheck": "tsc --noEmit"
51
51
  }
52
52
  }