Skip to content

Commit

Permalink
Added new modifications from API and new user addresses dealing system
Browse files Browse the repository at this point in the history
  • Loading branch information
marcvelmer committed Aug 27, 2024
1 parent e486206 commit c744d01
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 39 deletions.
53 changes: 39 additions & 14 deletions src/api/remote-signer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ enum RemoteSignerAPIMethods {
REGISTER = '/users',
LOGIN = '/auth/login',
REFRESH = '/auth/refresh',
ADDRESS = '/users/address',
ADDRESSES = '/auth/addresses',
SIGN_TX = '/transactions',
SIGN = '/transactions/message',
}
Expand All @@ -31,11 +31,11 @@ export interface IRemoteSignerRefreshResponse {
token: string;
}

export interface IRemoteSignerAddressResponse {
export interface IRemoteSignerAddressesResponse {
/**
* The address of the remote signer
* The list of addresses
*/
address: string;
addresses: Array<string>;
}

export interface IRemoteSignerSignTxResponse {
Expand Down Expand Up @@ -65,11 +65,24 @@ export abstract class RemoteSignerAPI extends API {
*
* @param url - API endpoint URL
* @param email - The email address
* @param firstName - The first name
* @param lastName - The last name
* @param password - The password
*/
public static register(url: string, email: string, password: string): Promise<IRemoteSignerRegisterResponse> {
public static register(
url: string,
email: string,
firstName: string,
lastName: string,
password: string
): Promise<IRemoteSignerRegisterResponse> {
return axios
.post<IRemoteSignerRegisterResponse>(url + RemoteSignerAPIMethods.REGISTER, { email, password })
.post<IRemoteSignerRegisterResponse>(url + RemoteSignerAPIMethods.REGISTER, {
email,
firstName,
lastName,
password,
})
.then((response) => response.data)
.catch(this.isApiError);
}
Expand Down Expand Up @@ -106,19 +119,19 @@ export abstract class RemoteSignerAPI extends API {
}

/**
* Gets the address of the remote signer.
* Gets the writable addresses of the logged-in user.
*
* @param url - API endpoint URL
* @param authToken - Authentication token
*/
public static address(url: string, authToken: string): Promise<IRemoteSignerAddressResponse> {
public static addresses(url: string, authToken: string): Promise<IRemoteSignerAddressesResponse> {
return axios
.get<IRemoteSignerAddressResponse>(url + RemoteSignerAPIMethods.ADDRESS, {
.get<IRemoteSignerAddressesResponse>(url + RemoteSignerAPIMethods.ADDRESSES, {
headers: {
Authorization: 'Bearer ' + authToken,
},
})
.then((response) => response.data)
.then((response) => JSON.parse(Buffer.from(response.data as any, 'base64').toString()))
.catch(this.isApiError);
}

Expand All @@ -127,13 +140,19 @@ export abstract class RemoteSignerAPI extends API {
*
* @param url - API endpoint URL
* @param authToken - Authentication token
* @param address - The address
* @param payload - The transaction payload
*/
public static signTransaction(url: string, authToken: string, payload: string): Promise<IRemoteSignerSignTxResponse> {
public static signTransaction(
url: string,
authToken: string,
address: string,
payload: string
): Promise<IRemoteSignerSignTxResponse> {
return axios
.post<IRemoteSignerSignTxResponse>(
url + RemoteSignerAPIMethods.SIGN_TX,
{ txPayload: payload },
{ txPayload: payload, address },
{
headers: {
Authorization: 'Bearer ' + authToken,
Expand All @@ -149,13 +168,19 @@ export abstract class RemoteSignerAPI extends API {
*
* @param url - API endpoint URL
* @param authToken - Authentication token
* @param address - The address
* @param payload - The payload
*/
public static sign(url: string, authToken: string, payload: string): Promise<IRemoteSignerSignResponse> {
public static sign(
url: string,
authToken: string,
address: string,
payload: string
): Promise<IRemoteSignerSignResponse> {
return axios
.post<IRemoteSignerSignResponse>(
url + RemoteSignerAPIMethods.SIGN,
{ payload },
{ address, payload },
{
headers: {
Authorization: 'Bearer ' + authToken,
Expand Down
56 changes: 35 additions & 21 deletions src/services/remote-signer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Service, ServiceProperties } from './service';
import { RemoteSignerAPI } from '../api';
import invariant from 'tiny-invariant';
import { RemoteSigner } from '../types';
import { RemoteSigner, RemoteSignerCredentials } from '../types';
import { toUtf8Bytes } from '@ethersproject/strings';
import { Bytes } from '@ethersproject/bytes';

Expand All @@ -27,31 +27,32 @@ export class RemoteSignerService extends Service implements RemoteSignerServiceP
/**
* Registers a new user using email and password.
*
* @param email - The email address
* @param firstName - The first name
* @param lastName - The last name
* @param password - The password
* @returns The JWT token
*/
register(): Promise<string> {
register(email: string, firstName: string, lastName: string, password: string): Promise<string> {
invariant(this.remoteSigner.url, 'No URL set');
invariant(this.remoteSigner.credentials, 'No authentication data set');
return RemoteSignerAPI.register(
this.remoteSigner.url,
this.remoteSigner.credentials.email,
this.remoteSigner.credentials.password
).then((response) => response.token);
return RemoteSignerAPI.register(this.remoteSigner.url, email, firstName, lastName, password).then(
(response) => response.token
);
}

/**
* Logs in to the remote signer.
*
* @returns The JWT token
*/
login(): Promise<string> {
login(credentials?: RemoteSignerCredentials): Promise<string> {
invariant(this.remoteSigner.url, 'No URL set');
invariant(this.remoteSigner.credentials, 'No authentication data set');
return RemoteSignerAPI.login(
this.remoteSigner.url,
this.remoteSigner.credentials.email,
this.remoteSigner.credentials.password
).then((response) => response.token);
const login = {
email: credentials.email ?? this.remoteSigner.credentials.email,
password: credentials.password ?? this.remoteSigner.credentials.password,
};
return RemoteSignerAPI.login(this.remoteSigner.url, login.email, login.password).then((response) => response.token);
}

/**
Expand All @@ -61,6 +62,7 @@ export class RemoteSignerService extends Service implements RemoteSignerServiceP
*/
refresh(): Promise<string> {
invariant(this.remoteSigner.url, 'No URL set');
invariant(this.remoteSigner.token, 'No auth token set');
return RemoteSignerAPI.refresh(this.remoteSigner.url, this.remoteSigner.token).then((response) => response.token);
}

Expand All @@ -72,30 +74,42 @@ export class RemoteSignerService extends Service implements RemoteSignerServiceP
getAddress(): Promise<string> {
invariant(this.remoteSigner.url, 'No URL set');
invariant(this.remoteSigner.token, 'No JWT token set');
return RemoteSignerAPI.address(this.remoteSigner.url, this.remoteSigner.token).then((response) => response.address);
return RemoteSignerAPI.addresses(this.remoteSigner.url, this.remoteSigner.token).then((response) => {
if (response.addresses?.length === 0) throw new Error('No addresses found');
this.remoteSigner.address = response.addresses[0];
return this.remoteSigner.address;
});
}

signTxPayload(payload: string | Bytes): Promise<string> {
invariant(this.remoteSigner.url, 'No URL set');
invariant(this.remoteSigner.token, 'No JWT token set');
invariant(this.remoteSigner.address, 'No address set');

const payloadBytes = typeof payload === 'string' ? toUtf8Bytes(payload) : payload;
const payloadBase64 = Buffer.from(Uint8Array.from(payloadBytes)).toString('base64');

return RemoteSignerAPI.signTransaction(this.remoteSigner.url, this.remoteSigner.token, payloadBase64).then(
(response) => response.txPayload
);
return RemoteSignerAPI.signTransaction(
this.remoteSigner.url,
this.remoteSigner.token,
this.remoteSigner.address,
payloadBase64
).then((response) => response.txPayload);
}

signPayload(payload: string | Bytes): Promise<string> {
invariant(this.remoteSigner.url, 'No URL set');
invariant(this.remoteSigner.token, 'No JWT token set');
invariant(this.remoteSigner.address, 'No address set');

const payloadBytes = typeof payload === 'string' ? toUtf8Bytes(payload) : payload;
const payloadBase64 = Buffer.from(Uint8Array.from(payloadBytes)).toString('base64');

return RemoteSignerAPI.sign(this.remoteSigner.url, this.remoteSigner.token, payloadBase64).then(
(response) => response.signature
);
return RemoteSignerAPI.sign(
this.remoteSigner.url,
this.remoteSigner.token,
this.remoteSigner.address,
payloadBase64
).then((response) => response.signature);
}
}
27 changes: 23 additions & 4 deletions src/types/remote-signer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { Provider, TransactionRequest } from '@ethersproject/providers';
import { Bytes } from '@ethersproject/bytes';
import { Signer } from '@ethersproject/abstract-signer';
import { RemoteSignerService } from '../services';
import invariant from 'tiny-invariant';
import { isAddress } from '@ethersproject/address';

export type RemoteSignerProperties = {
url: string;
Expand All @@ -18,6 +20,7 @@ export class RemoteSigner extends Signer {
public url: string;
public credentials: RemoteSignerCredentials;
public token: string;
private _address: string;
private _remoteSignerService: RemoteSignerService;

constructor(params: Partial<RemoteSignerProperties>) {
Expand All @@ -26,15 +29,19 @@ export class RemoteSigner extends Signer {
this.remoteSignerService = new RemoteSignerService({ remoteSigner: this });
}

async register(): Promise<string> {
return this.remoteSignerService.register().then((token) => {
async register(email: string, firstName: string, lastName: string, password: string): Promise<string> {
return this.remoteSignerService.register(email, firstName, lastName, password).then((token) => {
this.token = token;
return token;
});
}

async login(): Promise<string> {
return this.remoteSignerService.login().then((token) => {
async login(credentials?: RemoteSignerCredentials): Promise<string> {
const login = {
email: credentials?.email ?? this.credentials.email,
password: credentials?.password ?? this.credentials.password,
};
return this.remoteSignerService.login(login).then((token) => {
this.token = token;
return token;
});
Expand All @@ -56,6 +63,9 @@ export class RemoteSigner extends Signer {
}

async getAddress(): Promise<string> {
if (this.address) {
return this.address;
}
return this.remoteSignerService.getAddress();
}

Expand All @@ -74,4 +84,13 @@ export class RemoteSigner extends Signer {
set remoteSignerService(value: RemoteSignerService) {
this._remoteSignerService = value;
}

get address(): string {
return this._address;
}

set address(value: string) {
invariant(isAddress(value), 'Incorrect address');
this._address = value;
}
}

0 comments on commit c744d01

Please sign in to comment.