@account-kit/signer 4.26.0 → 4.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/base.d.ts +4 -4
- package/dist/esm/base.js +2 -2
- package/dist/esm/base.js.map +1 -1
- package/dist/esm/client/base.d.ts +49 -43
- package/dist/esm/client/base.js +166 -0
- package/dist/esm/client/base.js.map +1 -1
- package/dist/esm/client/index.d.ts +2 -50
- package/dist/esm/client/index.js +1 -162
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/client/types.d.ts +4 -7
- package/dist/esm/client/types.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/solanaSigner.d.ts +37 -4
- package/dist/esm/solanaSigner.js +107 -6
- package/dist/esm/solanaSigner.js.map +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/version.js.map +1 -1
- package/dist/types/base.d.ts +4 -4
- package/dist/types/base.d.ts.map +1 -1
- package/dist/types/client/base.d.ts +49 -43
- package/dist/types/client/base.d.ts.map +1 -1
- package/dist/types/client/index.d.ts +2 -50
- package/dist/types/client/index.d.ts.map +1 -1
- package/dist/types/client/types.d.ts +4 -7
- package/dist/types/client/types.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/solanaSigner.d.ts +37 -4
- package/dist/types/solanaSigner.d.ts.map +1 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +6 -4
- package/src/base.ts +5 -5
- package/src/client/base.ts +171 -49
- package/src/client/index.ts +1 -177
- package/src/client/types.ts +4 -7
- package/src/index.ts +1 -0
- package/src/solanaSigner.ts +155 -8
- package/src/version.ts +1 -1
package/src/solanaSigner.ts
CHANGED
|
@@ -1,17 +1,28 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Connection,
|
|
2
3
|
PublicKey,
|
|
3
4
|
Transaction,
|
|
4
|
-
|
|
5
|
+
TransactionInstruction,
|
|
6
|
+
TransactionMessage,
|
|
7
|
+
VersionedTransaction,
|
|
5
8
|
} from "@solana/web3.js";
|
|
6
9
|
import { size, slice, toBytes, toHex, type ByteArray, type Hex } from "viem";
|
|
7
10
|
import type { BaseSignerClient } from "./client/base";
|
|
8
11
|
import { NotAuthenticatedError } from "./errors.js";
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
/**
|
|
14
|
+
* The SolanaSigner class is used to sign transactions and messages for the Solana blockchain.
|
|
15
|
+
* It provides methods to add signatures to transactions and sign messages.
|
|
16
|
+
*/
|
|
11
17
|
export class SolanaSigner {
|
|
12
|
-
|
|
13
|
-
public address: string;
|
|
18
|
+
readonly alchemyClient: BaseSignerClient;
|
|
19
|
+
public readonly address: string;
|
|
14
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Constructor for the SolanaSigner class which is a wrapper around the alchemy client, and is more focused on the solana web3
|
|
23
|
+
*
|
|
24
|
+
* @param {object} client This is the client that will be used to sign the transaction, and we are just having functions on top of it.
|
|
25
|
+
*/
|
|
15
26
|
constructor(client: BaseSignerClient) {
|
|
16
27
|
this.alchemyClient = client;
|
|
17
28
|
if (!client.getUser()) throw new Error("Must be authenticated!");
|
|
@@ -20,8 +31,14 @@ export class SolanaSigner {
|
|
|
20
31
|
this.address = client.getUser()!.solanaAddress!;
|
|
21
32
|
}
|
|
22
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Adds a signature of the client user to a transaction
|
|
36
|
+
*
|
|
37
|
+
* @param {Transaction | VersionedTransaction} transaction - The transaction to add the signature to
|
|
38
|
+
* @returns {Promise<Transaction | VersionedTransaction >} The transaction with the signature added
|
|
39
|
+
*/
|
|
23
40
|
async addSignature(
|
|
24
|
-
|
|
41
|
+
transaction: Transaction | VersionedTransaction
|
|
25
42
|
): Promise<Transaction | VersionedTransaction> {
|
|
26
43
|
const user = this.alchemyClient.getUser();
|
|
27
44
|
if (!user) {
|
|
@@ -33,19 +50,25 @@ export class SolanaSigner {
|
|
|
33
50
|
}
|
|
34
51
|
|
|
35
52
|
const fromKey = new PublicKey(user.solanaAddress);
|
|
36
|
-
const messageToSign = this.getMessageToSign(
|
|
53
|
+
const messageToSign = this.getMessageToSign(transaction);
|
|
37
54
|
const signature = await this.alchemyClient.signRawMessage(
|
|
38
55
|
messageToSign,
|
|
39
56
|
"SOLANA"
|
|
40
57
|
);
|
|
41
58
|
|
|
42
|
-
|
|
59
|
+
transaction.addSignature(
|
|
43
60
|
fromKey,
|
|
44
61
|
Buffer.from(toBytes(this.formatSignatureForSolana(signature)))
|
|
45
62
|
);
|
|
46
|
-
return
|
|
63
|
+
return transaction;
|
|
47
64
|
}
|
|
48
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Signs a message
|
|
68
|
+
*
|
|
69
|
+
* @param {Uint8Array} message - The message to sign
|
|
70
|
+
* @returns {Promise<ByteArray>} The signature of the message
|
|
71
|
+
*/
|
|
49
72
|
async signMessage(message: Uint8Array): Promise<ByteArray> {
|
|
50
73
|
const user = this.alchemyClient.getUser();
|
|
51
74
|
if (!user) {
|
|
@@ -65,6 +88,127 @@ export class SolanaSigner {
|
|
|
65
88
|
return toBytes(this.formatSignatureForSolana(signature));
|
|
66
89
|
}
|
|
67
90
|
|
|
91
|
+
async createTransfer(
|
|
92
|
+
instructions: TransactionInstruction[],
|
|
93
|
+
connection: Connection,
|
|
94
|
+
version?: "versioned"
|
|
95
|
+
): Promise<VersionedTransaction>;
|
|
96
|
+
async createTransfer(
|
|
97
|
+
instructions: TransactionInstruction[],
|
|
98
|
+
connection: Connection,
|
|
99
|
+
version?: "legacy"
|
|
100
|
+
): Promise<Transaction>;
|
|
101
|
+
async createTransfer(
|
|
102
|
+
instructions: TransactionInstruction[],
|
|
103
|
+
connection: Connection
|
|
104
|
+
): Promise<VersionedTransaction>;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Creates a transfer transaction. Used for the SolanaCard example.
|
|
108
|
+
*
|
|
109
|
+
* @param {TransactionInstruction[]} instructions - The instructions to add to the transaction
|
|
110
|
+
* @param {Connection} connection - The connection to use for the transaction
|
|
111
|
+
* @param {"versioned" | "legacy"} [version] - The version of the transaction
|
|
112
|
+
* @returns {Promise<Transaction | VersionedTransaction>} The transfer transaction
|
|
113
|
+
*/
|
|
114
|
+
async createTransfer(
|
|
115
|
+
instructions: TransactionInstruction[],
|
|
116
|
+
connection: Connection,
|
|
117
|
+
version?: string
|
|
118
|
+
): Promise<Transaction | VersionedTransaction> {
|
|
119
|
+
const blockhash = (await connection.getLatestBlockhash()).blockhash;
|
|
120
|
+
|
|
121
|
+
let transferTransaction;
|
|
122
|
+
|
|
123
|
+
if (version === "legacy") {
|
|
124
|
+
// Legacy transaction
|
|
125
|
+
transferTransaction = instructions.reduce(
|
|
126
|
+
(tx, instruction) => tx.add(instruction),
|
|
127
|
+
new Transaction()
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
// Get a recent block hash
|
|
131
|
+
transferTransaction.recentBlockhash = blockhash;
|
|
132
|
+
// Set the signer
|
|
133
|
+
transferTransaction.feePayer = new PublicKey(this.address);
|
|
134
|
+
} else {
|
|
135
|
+
// VersionedTransaction
|
|
136
|
+
const txMessage = new TransactionMessage({
|
|
137
|
+
payerKey: new PublicKey(this.address),
|
|
138
|
+
recentBlockhash: blockhash,
|
|
139
|
+
instructions,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
const versionedTxMessage = txMessage.compileToV0Message();
|
|
143
|
+
transferTransaction = new VersionedTransaction(versionedTxMessage);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return transferTransaction;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Adds sponsorship to a transaction. Used to have a party like Alchemy pay for the transaction.
|
|
151
|
+
*
|
|
152
|
+
* @param {TransactionInstruction[]} instructions - The instructions to add to the transaction
|
|
153
|
+
* @param {Connection} connection - The connection to use for the transaction
|
|
154
|
+
* @param {string} [policyId] - The policy ID to add sponsorship to
|
|
155
|
+
* @returns {Promise<VersionedTransaction>} The transaction with sponsorship added
|
|
156
|
+
*/
|
|
157
|
+
async addSponsorship(
|
|
158
|
+
instructions: TransactionInstruction[],
|
|
159
|
+
connection: Connection,
|
|
160
|
+
policyId: string
|
|
161
|
+
): Promise<VersionedTransaction> {
|
|
162
|
+
const { blockhash } = await connection.getLatestBlockhash({
|
|
163
|
+
commitment: "finalized",
|
|
164
|
+
});
|
|
165
|
+
const message = new TransactionMessage({
|
|
166
|
+
// Right now the backend will rewrite this payer Key to the server's address
|
|
167
|
+
payerKey: new PublicKey(this.address),
|
|
168
|
+
recentBlockhash: blockhash,
|
|
169
|
+
instructions,
|
|
170
|
+
}).compileToV0Message();
|
|
171
|
+
const versionedTransaction = new VersionedTransaction(message);
|
|
172
|
+
const serializedTransaction = Buffer.from(
|
|
173
|
+
versionedTransaction.serialize()
|
|
174
|
+
).toString("base64");
|
|
175
|
+
const body = JSON.stringify({
|
|
176
|
+
id: crypto?.randomUUID() ?? Math.floor(Math.random() * 1000000),
|
|
177
|
+
jsonrpc: "2.0",
|
|
178
|
+
method: "alchemy_requestFeePayer",
|
|
179
|
+
params: [
|
|
180
|
+
{
|
|
181
|
+
policyId,
|
|
182
|
+
serializedTransaction,
|
|
183
|
+
},
|
|
184
|
+
],
|
|
185
|
+
});
|
|
186
|
+
const options = {
|
|
187
|
+
method: "POST",
|
|
188
|
+
headers: {
|
|
189
|
+
accept: "application/json",
|
|
190
|
+
"content-type": "application/json",
|
|
191
|
+
},
|
|
192
|
+
body,
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
const response = await fetch(
|
|
196
|
+
// TODO: Use the connection??
|
|
197
|
+
connection.rpcEndpoint,
|
|
198
|
+
options
|
|
199
|
+
);
|
|
200
|
+
const jsonResponse = await response.json();
|
|
201
|
+
if (!jsonResponse?.result?.serializedTransaction)
|
|
202
|
+
throw new Error(
|
|
203
|
+
`Response doesn't include the serializedTransaction ${JSON.stringify(
|
|
204
|
+
jsonResponse
|
|
205
|
+
)}`
|
|
206
|
+
);
|
|
207
|
+
return VersionedTransaction.deserialize(
|
|
208
|
+
decodeBase64(jsonResponse.result.serializedTransaction)
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
68
212
|
private formatSignatureForSolana(signature: Hex): Hex {
|
|
69
213
|
if (size(signature) === 64) return signature;
|
|
70
214
|
|
|
@@ -81,3 +225,6 @@ export class SolanaSigner {
|
|
|
81
225
|
return toHex(messageToSign);
|
|
82
226
|
}
|
|
83
227
|
}
|
|
228
|
+
function decodeBase64(serializedTransaction: string): Uint8Array {
|
|
229
|
+
return Buffer.from(serializedTransaction, "base64");
|
|
230
|
+
}
|
package/src/version.ts
CHANGED