@account-kit/signer 4.52.4 → 4.53.1-alpha.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 +41 -1
- package/dist/esm/base.js +116 -39
- package/dist/esm/base.js.map +1 -1
- package/dist/esm/client/base.d.ts +14 -1
- package/dist/esm/client/base.js +24 -0
- package/dist/esm/client/base.js.map +1 -1
- package/dist/esm/client/index.d.ts +29 -1
- package/dist/esm/client/index.js +37 -0
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/client/types.d.ts +13 -5
- 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/metrics.d.ts +1 -1
- package/dist/esm/metrics.js.map +1 -1
- package/dist/esm/signer.d.ts +3 -0
- package/dist/esm/signer.js.map +1 -1
- package/dist/esm/solanaSigner.js +2 -40
- package/dist/esm/solanaSigner.js.map +1 -1
- package/dist/esm/types.d.ts +1 -0
- package/dist/esm/types.js +1 -0
- package/dist/esm/types.js.map +1 -1
- package/dist/esm/utils/solana.d.ts +21 -0
- package/dist/esm/utils/solana.js +72 -0
- package/dist/esm/utils/solana.js.map +1 -0
- 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 +41 -1
- package/dist/types/base.d.ts.map +1 -1
- package/dist/types/client/base.d.ts +14 -1
- package/dist/types/client/base.d.ts.map +1 -1
- package/dist/types/client/index.d.ts +29 -1
- package/dist/types/client/index.d.ts.map +1 -1
- package/dist/types/client/types.d.ts +13 -5
- 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/metrics.d.ts +1 -1
- package/dist/types/metrics.d.ts.map +1 -1
- package/dist/types/signer.d.ts +3 -0
- package/dist/types/signer.d.ts.map +1 -1
- package/dist/types/solanaSigner.d.ts.map +1 -1
- package/dist/types/types.d.ts +1 -0
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/utils/solana.d.ts +22 -0
- package/dist/types/utils/solana.d.ts.map +1 -0
- package/dist/types/version.d.ts +1 -1
- package/dist/types/version.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/base.ts +175 -12
- package/src/client/base.ts +27 -0
- package/src/client/index.ts +37 -0
- package/src/client/types.ts +19 -6
- package/src/index.ts +4 -0
- package/src/metrics.ts +1 -0
- package/src/signer.ts +4 -0
- package/src/solanaSigner.ts +5 -49
- package/src/types.ts +1 -0
- package/src/utils/solana.ts +100 -0
- package/src/version.ts +1 -1
package/src/client/base.ts
CHANGED
|
@@ -47,6 +47,7 @@ import type {
|
|
|
47
47
|
OauthProviderInfo,
|
|
48
48
|
IdTokenOnly,
|
|
49
49
|
AuthMethods,
|
|
50
|
+
SmsAuthParams,
|
|
50
51
|
} from "./types.js";
|
|
51
52
|
import { VERSION } from "../version.js";
|
|
52
53
|
import { secp256k1 } from "@noble/curves/secp256k1";
|
|
@@ -182,6 +183,18 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
182
183
|
return response;
|
|
183
184
|
}
|
|
184
185
|
|
|
186
|
+
if (params.type === "sms") {
|
|
187
|
+
this.eventEmitter.emit("authenticating", { type: "otp" });
|
|
188
|
+
const { phone } = params;
|
|
189
|
+
const publicKey = await this.initSessionStamper();
|
|
190
|
+
|
|
191
|
+
const response = await this.request("/v1/signup", {
|
|
192
|
+
phone,
|
|
193
|
+
targetPublicKey: publicKey,
|
|
194
|
+
});
|
|
195
|
+
return response;
|
|
196
|
+
}
|
|
197
|
+
|
|
185
198
|
this.eventEmitter.emit("authenticating", { type: "passkey" });
|
|
186
199
|
// Passkey account creation flow
|
|
187
200
|
const { attestation, challenge } = await this.getWebAuthnAttestation(
|
|
@@ -218,6 +231,10 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
218
231
|
params: Omit<EmailAuthParams, "targetPublicKey">,
|
|
219
232
|
): Promise<{ orgId: string; otpId?: string; multiFactors?: MfaFactor[] }>;
|
|
220
233
|
|
|
234
|
+
public abstract initSmsAuth(
|
|
235
|
+
params: Omit<SmsAuthParams, "targetPublicKey">,
|
|
236
|
+
): Promise<{ orgId: string; otpId?: string }>;
|
|
237
|
+
|
|
221
238
|
public abstract completeAuthWithBundle(params: {
|
|
222
239
|
bundle: string;
|
|
223
240
|
orgId: string;
|
|
@@ -645,6 +662,16 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
645
662
|
return this.request("/v1/lookup", { email });
|
|
646
663
|
};
|
|
647
664
|
|
|
665
|
+
/**
|
|
666
|
+
* Looks up information based on a phone number.
|
|
667
|
+
*
|
|
668
|
+
* @param {string} phone the phone number to look up
|
|
669
|
+
* @returns {Promise<any>} the result of the lookup request
|
|
670
|
+
*/
|
|
671
|
+
public lookupUserByPhone = async (phone: string) => {
|
|
672
|
+
return this.request("/v1/lookup", { phone });
|
|
673
|
+
};
|
|
674
|
+
|
|
648
675
|
/**
|
|
649
676
|
* This will sign a message with the user's private key, without doing any transformations on the message.
|
|
650
677
|
* For SignMessage or SignTypedData, the caller should hash the message before calling this method and pass
|
package/src/client/index.ts
CHANGED
|
@@ -19,6 +19,7 @@ import type {
|
|
|
19
19
|
AuthLinkingPrompt,
|
|
20
20
|
GetWebAuthnAttestationResult,
|
|
21
21
|
IdTokenOnly,
|
|
22
|
+
SmsAuthParams,
|
|
22
23
|
} from "./types.js";
|
|
23
24
|
import { MfaRequiredError } from "../errors.js";
|
|
24
25
|
import { parseMfaError } from "../utils/parseMfaError.js";
|
|
@@ -160,6 +161,42 @@ export class AlchemySignerWebClient extends BaseSignerClient<ExportWalletParams>
|
|
|
160
161
|
}
|
|
161
162
|
};
|
|
162
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Begin authenticating a user through sms. Initializes the iframe stamper to get the target public key.
|
|
166
|
+
* This method sends a text message to the user to complete their login
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* ```ts
|
|
170
|
+
* import { AlchemySignerWebClient } from "@account-kit/signer";
|
|
171
|
+
*
|
|
172
|
+
* const client = new AlchemySignerWebClient({
|
|
173
|
+
* connection: {
|
|
174
|
+
* apiKey: "your-api-key",
|
|
175
|
+
* },
|
|
176
|
+
* iframeConfig: {
|
|
177
|
+
* iframeContainerId: "signer-iframe-container",
|
|
178
|
+
* },
|
|
179
|
+
* });
|
|
180
|
+
*
|
|
181
|
+
* const account = await client.initSmsAuth({ phone: "+1234567890" });
|
|
182
|
+
* ```
|
|
183
|
+
*
|
|
184
|
+
* @param {Omit<SmsAuthParams, "targetPublicKey">} params The parameters for sms authentication, excluding the target public key
|
|
185
|
+
* @returns {Promise<any>} The response from the authentication request
|
|
186
|
+
*/
|
|
187
|
+
public override initSmsAuth = async (
|
|
188
|
+
params: Omit<SmsAuthParams, "targetPublicKey">,
|
|
189
|
+
) => {
|
|
190
|
+
this.eventEmitter.emit("authenticating", { type: "otp" });
|
|
191
|
+
const { phone } = params;
|
|
192
|
+
const publicKey = await this.initSessionStamper();
|
|
193
|
+
|
|
194
|
+
return this.request("/v1/auth", {
|
|
195
|
+
phone,
|
|
196
|
+
targetPublicKey: publicKey,
|
|
197
|
+
});
|
|
198
|
+
};
|
|
199
|
+
|
|
163
200
|
/**
|
|
164
201
|
* Authenticates using an OTP code which was previously received via email.
|
|
165
202
|
*
|
package/src/client/types.ts
CHANGED
|
@@ -38,6 +38,10 @@ export type CreateAccountParams =
|
|
|
38
38
|
expirationSeconds?: number;
|
|
39
39
|
redirectParams?: URLSearchParams;
|
|
40
40
|
}
|
|
41
|
+
| {
|
|
42
|
+
type: "sms";
|
|
43
|
+
phone: string;
|
|
44
|
+
}
|
|
41
45
|
| {
|
|
42
46
|
type: "passkey";
|
|
43
47
|
email: string;
|
|
@@ -61,6 +65,11 @@ export type EmailAuthParams = {
|
|
|
61
65
|
multiFactors?: VerifyMfaParams[];
|
|
62
66
|
};
|
|
63
67
|
|
|
68
|
+
export type SmsAuthParams = {
|
|
69
|
+
phone: string;
|
|
70
|
+
targetPublicKey: string;
|
|
71
|
+
};
|
|
72
|
+
|
|
64
73
|
export type OauthParams = Extract<AuthParams, { type: "oauth" }> & {
|
|
65
74
|
expirationSeconds?: number;
|
|
66
75
|
fetchIdTokenOnly?: boolean;
|
|
@@ -131,6 +140,7 @@ export type SignerEndpoints = [
|
|
|
131
140
|
| (Omit<EmailAuthParams, "redirectParams"> & {
|
|
132
141
|
redirectParams?: string;
|
|
133
142
|
})
|
|
143
|
+
| SmsAuthParams
|
|
134
144
|
| {
|
|
135
145
|
passkey: {
|
|
136
146
|
challenge: string;
|
|
@@ -148,10 +158,12 @@ export type SignerEndpoints = [
|
|
|
148
158
|
},
|
|
149
159
|
{
|
|
150
160
|
Route: "/v1/auth";
|
|
151
|
-
Body:
|
|
152
|
-
redirectParams
|
|
153
|
-
|
|
154
|
-
|
|
161
|
+
Body:
|
|
162
|
+
| (Omit<EmailAuthParams, "redirectParams"> & {
|
|
163
|
+
redirectParams?: string;
|
|
164
|
+
multiFactors?: VerifyMfaParams[];
|
|
165
|
+
})
|
|
166
|
+
| SmsAuthParams;
|
|
155
167
|
Response: {
|
|
156
168
|
orgId: string;
|
|
157
169
|
otpId?: string;
|
|
@@ -161,7 +173,8 @@ export type SignerEndpoints = [
|
|
|
161
173
|
{
|
|
162
174
|
Route: "/v1/lookup";
|
|
163
175
|
Body: {
|
|
164
|
-
email
|
|
176
|
+
email?: string;
|
|
177
|
+
phone?: string;
|
|
165
178
|
};
|
|
166
179
|
Response: {
|
|
167
180
|
orgId: string | null;
|
|
@@ -334,7 +347,7 @@ export type SignerEndpoints = [
|
|
|
334
347
|
];
|
|
335
348
|
|
|
336
349
|
export type AuthenticatingEventMetadata = {
|
|
337
|
-
type: "email" | "passkey" | "oauth" | "otp" | "otpVerify";
|
|
350
|
+
type: "email" | "passkey" | "oauth" | "otp" | "otpVerify" | "sms";
|
|
338
351
|
};
|
|
339
352
|
|
|
340
353
|
export type AlchemySignerClientEvents = {
|
package/src/index.ts
CHANGED
|
@@ -21,3 +21,7 @@ export type * from "./solanaSigner.js";
|
|
|
21
21
|
export type * from "./types.js";
|
|
22
22
|
export { AlchemySignerStatus } from "./types.js";
|
|
23
23
|
export { SolanaSigner } from "./solanaSigner.js";
|
|
24
|
+
export {
|
|
25
|
+
createSolanaSponsoredTransaction,
|
|
26
|
+
createSolanaTransaction,
|
|
27
|
+
} from "./utils/solana.js";
|
package/src/metrics.ts
CHANGED
package/src/signer.ts
CHANGED
package/src/solanaSigner.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
import { size, slice, toBytes, toHex, type ByteArray, type Hex } from "viem";
|
|
10
10
|
import type { BaseSignerClient } from "./client/base";
|
|
11
11
|
import { NotAuthenticatedError } from "./errors.js";
|
|
12
|
+
import { createSolanaSponsoredTransaction } from "./utils/solana.js";
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* The SolanaSigner class is used to sign transactions and messages for the Solana blockchain.
|
|
@@ -159,53 +160,11 @@ export class SolanaSigner {
|
|
|
159
160
|
connection: Connection,
|
|
160
161
|
policyId: string,
|
|
161
162
|
): Promise<VersionedTransaction> {
|
|
162
|
-
|
|
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,
|
|
163
|
+
return createSolanaSponsoredTransaction(
|
|
169
164
|
instructions,
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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),
|
|
165
|
+
connection,
|
|
166
|
+
policyId,
|
|
167
|
+
this.address,
|
|
209
168
|
);
|
|
210
169
|
}
|
|
211
170
|
|
|
@@ -225,6 +184,3 @@ export class SolanaSigner {
|
|
|
225
184
|
return toHex(messageToSign);
|
|
226
185
|
}
|
|
227
186
|
}
|
|
228
|
-
function decodeBase64(serializedTransaction: string): Uint8Array {
|
|
229
|
-
return Buffer.from(serializedTransaction, "base64");
|
|
230
|
-
}
|
package/src/types.ts
CHANGED
|
@@ -24,6 +24,7 @@ export enum AlchemySignerStatus {
|
|
|
24
24
|
AUTHENTICATING_EMAIL = "AUTHENTICATING_EMAIL",
|
|
25
25
|
AUTHENTICATING_OAUTH = "AUTHENTICATING_OAUTH",
|
|
26
26
|
AWAITING_EMAIL_AUTH = "AWAITING_EMAIL_AUTH",
|
|
27
|
+
AWAITING_SMS_AUTH = "AWAITING_SMS_AUTH",
|
|
27
28
|
AWAITING_OTP_AUTH = "AWAITING_OTP_AUTH",
|
|
28
29
|
AWAITING_MFA_AUTH = "AWAITING_MFA_AUTH",
|
|
29
30
|
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { TransactionInstruction } from "@solana/web3.js";
|
|
2
|
+
import {
|
|
3
|
+
Connection,
|
|
4
|
+
PublicKey,
|
|
5
|
+
TransactionMessage,
|
|
6
|
+
VersionedTransaction,
|
|
7
|
+
} from "@solana/web3.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* This function wraps instructions in a sponsored transaction using Alchemy's fee payer service
|
|
11
|
+
*
|
|
12
|
+
* @param {TransactionInstruction[]} instructions - The instructions to add sponsorship to
|
|
13
|
+
* @param {Connection} connection - The connection to use
|
|
14
|
+
* @param {string} policyId - The policy id to use
|
|
15
|
+
* @param {string} address - The address to use
|
|
16
|
+
* @returns {Promise<VersionedTransaction>} - The sponsored transaction
|
|
17
|
+
*/
|
|
18
|
+
export async function createSolanaSponsoredTransaction(
|
|
19
|
+
instructions: TransactionInstruction[],
|
|
20
|
+
connection: Connection,
|
|
21
|
+
policyId: string,
|
|
22
|
+
address: string,
|
|
23
|
+
): Promise<VersionedTransaction> {
|
|
24
|
+
const { blockhash } = await connection.getLatestBlockhash({
|
|
25
|
+
commitment: "finalized",
|
|
26
|
+
});
|
|
27
|
+
const message = new TransactionMessage({
|
|
28
|
+
// Right now the backend will rewrite this payer Key to the server's address
|
|
29
|
+
payerKey: new PublicKey(address),
|
|
30
|
+
recentBlockhash: blockhash,
|
|
31
|
+
instructions,
|
|
32
|
+
}).compileToV0Message();
|
|
33
|
+
const versionedTransaction = new VersionedTransaction(message);
|
|
34
|
+
const serializedTransaction = Buffer.from(
|
|
35
|
+
versionedTransaction.serialize(),
|
|
36
|
+
).toString("base64");
|
|
37
|
+
const body = JSON.stringify({
|
|
38
|
+
id: crypto?.randomUUID() ?? Math.floor(Math.random() * 1000000),
|
|
39
|
+
jsonrpc: "2.0",
|
|
40
|
+
method: "alchemy_requestFeePayer",
|
|
41
|
+
params: [
|
|
42
|
+
{
|
|
43
|
+
policyId,
|
|
44
|
+
serializedTransaction,
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
});
|
|
48
|
+
const options = {
|
|
49
|
+
method: "POST",
|
|
50
|
+
headers: {
|
|
51
|
+
accept: "application/json",
|
|
52
|
+
"content-type": "application/json",
|
|
53
|
+
},
|
|
54
|
+
body,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const response = await fetch(
|
|
58
|
+
// TODO: Use the connection??
|
|
59
|
+
connection.rpcEndpoint,
|
|
60
|
+
options,
|
|
61
|
+
);
|
|
62
|
+
const jsonResponse = await response.json();
|
|
63
|
+
if (!jsonResponse?.result?.serializedTransaction)
|
|
64
|
+
throw new Error(
|
|
65
|
+
`Response doesn't include the serializedTransaction ${JSON.stringify(
|
|
66
|
+
jsonResponse,
|
|
67
|
+
)}`,
|
|
68
|
+
);
|
|
69
|
+
return VersionedTransaction.deserialize(
|
|
70
|
+
decodeBase64(jsonResponse.result.serializedTransaction),
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Creates a regular (non-sponsored) Solana transaction from instructions
|
|
76
|
+
*
|
|
77
|
+
* @param {TransactionInstruction[]} instructions - The instructions to create transaction from
|
|
78
|
+
* @param {Connection} connection - The connection to use
|
|
79
|
+
* @param {string} address - The payer address
|
|
80
|
+
* @returns {Promise<VersionedTransaction>} - The transaction
|
|
81
|
+
*/
|
|
82
|
+
export async function createSolanaTransaction(
|
|
83
|
+
instructions: TransactionInstruction[],
|
|
84
|
+
connection: Connection,
|
|
85
|
+
address: string,
|
|
86
|
+
): Promise<VersionedTransaction> {
|
|
87
|
+
const { blockhash } = await connection.getLatestBlockhash({
|
|
88
|
+
commitment: "finalized",
|
|
89
|
+
});
|
|
90
|
+
const message = new TransactionMessage({
|
|
91
|
+
payerKey: new PublicKey(address),
|
|
92
|
+
recentBlockhash: blockhash,
|
|
93
|
+
instructions,
|
|
94
|
+
}).compileToV0Message();
|
|
95
|
+
return new VersionedTransaction(message);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function decodeBase64(serializedTransaction: string): Uint8Array {
|
|
99
|
+
return Buffer.from(serializedTransaction, "base64");
|
|
100
|
+
}
|
package/src/version.ts
CHANGED