Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions packages/wallets/src/signers/evm-api-key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ export class EVMApiKeySigner implements Signer {
return this.config.locator;
}

async sign() {
return await Promise.reject(
new Error(
"API key signers do not support direct transaction signing - transaction are handled automatically by the backend"
)
);
}
async signMessage() {
return await Promise.reject(
new Error(
Expand Down
12 changes: 8 additions & 4 deletions packages/wallets/src/signers/evm-external-wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ export class EVMExternalWalletSigner implements Signer {
return this.config.locator;
}

async signMessage(message: string) {
async sign(payload: string): Promise<{ signature: string }> {
if (this.provider != null) {
const signature = await this.provider.request({
method: "personal_sign",
params: [message, this._address] as any,
params: [payload, this._address] as any,
});
if (signature == null) {
throw new Error(
Expand All @@ -41,7 +41,7 @@ export class EVMExternalWalletSigner implements Signer {
if (this.viemAccount?.signMessage != null) {
const signature = await this.viemAccount.signMessage({
message: {
raw: message as `0x${string}`,
raw: payload as `0x${string}`,
},
});
if (signature == null) {
Expand All @@ -54,7 +54,11 @@ export class EVMExternalWalletSigner implements Signer {
throw new Error("No signer provider or viem account provided");
}

async signMessage(message: string) {
return await this.sign(message);
}

async signTransaction(transaction: string) {
return await this.signMessage(transaction);
return await this.sign(transaction);
}
}
12 changes: 9 additions & 3 deletions packages/wallets/src/signers/non-custodial/ncs-evm-signer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ export class EVMNonCustodialSigner extends NonCustodialSigner {
super(config);
}

async signMessage(message: string) {
async signMessage(message: string, raw?: boolean) {
if (raw && message) {
if (!isHex(message)) {
throw new Error("Invalid hex string in signMessage raw argument");
}
return await this.sign(message);
}
const messageRaw = isHex(message) ? (message as Hex) : toHex(message);
const messageToSign = PersonalMessage.getSignPayload(messageRaw);
return await this.sign(messageToSign);
Expand All @@ -18,11 +24,11 @@ export class EVMNonCustodialSigner extends NonCustodialSigner {
return await this.sign(transaction);
}

private async sign(raw: string): Promise<{ signature: string }> {
async sign(payload: string): Promise<{ signature: string }> {
await this.handleAuthRequired();
const jwt = this.getJwtOrThrow();

const hexString = raw.replace("0x", "");
const hexString = payload.replace("0x", "");

const res = await this.config.clientTEEConnection?.sendAction({
event: "request:sign",
Expand Down
1 change: 1 addition & 0 deletions packages/wallets/src/signers/non-custodial/ncs-signer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export abstract class NonCustodialSigner implements Signer {
return this.config.address;
}

abstract sign(payload: string): Promise<BaseSignResult>;
abstract signMessage(message: string): Promise<BaseSignResult>;

private async initialize() {
Expand Down
18 changes: 11 additions & 7 deletions packages/wallets/src/signers/non-custodial/ncs-solana-signer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,20 @@ export class SolanaNonCustodialSigner extends NonCustodialSigner {
}

async signMessage() {
return await Promise.reject(new Error("signMessage method not implemented for email signer"));
return await Promise.reject(new Error("signMessage method not implemented for Solana email signer"));
}

async signTransaction(transaction: string): Promise<{ signature: string }> {
await this.handleAuthRequired();
const jwt = this.getJwtOrThrow();

const transactionBytes = base58.decode(transaction);
const deserializedTransaction = VersionedTransaction.deserialize(transactionBytes);
const messageData = deserializedTransaction.message.serialize();
const messageData = base58.encode(deserializedTransaction.message.serialize());

return await this.sign(messageData);
}

async sign(payload: string): Promise<{ signature: string }> {
await this.handleAuthRequired();
const jwt = this.getJwtOrThrow();

const res = await this.config.clientTEEConnection?.sendAction({
event: "request:sign",
Expand All @@ -30,7 +34,7 @@ export class SolanaNonCustodialSigner extends NonCustodialSigner {
},
data: {
keyType: "ed25519",
bytes: base58.encode(messageData),
bytes: payload,
encoding: "base58",
},
},
Expand All @@ -42,7 +46,7 @@ export class SolanaNonCustodialSigner extends NonCustodialSigner {
}

if (res?.signature == null) {
throw new Error("Failed to sign transaction");
throw new Error("Failed to sign payload");
}
SolanaNonCustodialSigner.verifyPublicKeyFormat(res.publicKey);
return { signature: res.signature.bytes };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ export class StellarNonCustodialSigner extends NonCustodialSigner {
super(config);
}

async sign() {
return Promise.reject(new Error("sign method not implemented for stellar signer"));
}

async signMessage() {
return await Promise.reject(new Error("signMessage method not implemented for stellar signer"));
}
Expand Down
12 changes: 8 additions & 4 deletions packages/wallets/src/signers/passkey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ export class PasskeySigner implements Signer {
return this.config.locator;
}

async signMessage(message: string): Promise<PasskeySignResult> {
async sign(payload: string): Promise<PasskeySignResult> {
if (this.config.onSignWithPasskey) {
return await this.config.onSignWithPasskey(message);
return await this.config.onSignWithPasskey(payload);
}
const { signature, metadata } = await WebAuthnP256.sign({
credentialId: this.id,
challenge: message as `0x${string}`,
challenge: payload as `0x${string}`,
});

return {
Expand All @@ -31,7 +31,11 @@ export class PasskeySigner implements Signer {
};
}

async signMessage(message: string): Promise<PasskeySignResult> {
return await this.sign(message);
}

async signTransaction(transaction: string) {
return await this.signMessage(transaction);
return await this.sign(transaction);
}
}
4 changes: 4 additions & 0 deletions packages/wallets/src/signers/solana-api-key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ export class SolanaApiKeySigner implements Signer {
return this.config.locator;
}

async sign(payload: string) {
return await Promise.reject(new Error("sign method not implemented for solana api key signer"));
}

async signMessage() {
return await Promise.reject(
new Error(
Expand Down
4 changes: 4 additions & 0 deletions packages/wallets/src/signers/solana-external-wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ export class SolanaExternalWalletSigner implements Signer {
return this.config.locator;
}

async sign(payload: string) {
return await Promise.reject(new Error("sign method not implemented for solana external wallet signer"));
}

async signMessage() {
return await Promise.reject(new Error("signMessage method not implemented for solana external wallet signer"));
}
Expand Down
4 changes: 4 additions & 0 deletions packages/wallets/src/signers/stellar-external-wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ export class StellarExternalWalletSigner implements Signer {
return this.config.locator;
}

async sign(payload: string) {
return await Promise.reject(new Error("signMessage method not implemented for stellar external wallet signer"));
}

async signMessage() {
return await Promise.reject(new Error("signMessage method not implemented for stellar external wallet signer"));
}
Expand Down
1 change: 1 addition & 0 deletions packages/wallets/src/signers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ export interface Signer<T extends keyof SignResultMap = keyof SignResultMap> {
type: T;
locator(): string;
address?(): string;
sign(payload: string): Promise<SignResultMap[T]>;
signMessage(message: string): Promise<SignResultMap[T]>;
signTransaction(transaction: string): Promise<SignResultMap[T]>;
}
10 changes: 7 additions & 3 deletions packages/wallets/src/wallets/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -388,10 +388,14 @@ export class Wallet<C extends Chain> {
}
}

protected get isSolanaWallet(): boolean {
protected isSolanaWallet(): boolean {
return this.chain === "solana";
}

protected isStellarWallet(): boolean {
return this.chain === "stellar";
}

protected async approveTransactionAndWait(transactionId: string, options?: ApproveOptions) {
await this.approveTransactionInternal(transactionId, options);
await this.sleep(1_000); // Rule of thumb: tx won't be confirmed in less than 1 second
Expand All @@ -405,7 +409,7 @@ export class Wallet<C extends Chain> {
}

protected async approveSignatureInternal(signatureId: string, options?: ApproveOptions) {
if (this.isSolanaWallet) {
if (this.isSolanaWallet() || this.isStellarWallet()) {
throw new Error("Approving signatures is only supported for EVM smart wallets");
}

Expand Down Expand Up @@ -442,7 +446,7 @@ export class Wallet<C extends Chain> {
throw new InvalidSignerError(`Signer ${pendingApproval.signer} not found in pending approvals`);
}

return signer.signMessage(pendingApproval.message);
return signer.sign(pendingApproval.message);
})
);

Expand Down