Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: replaced requestId double with UUID v7 #11

Merged
merged 3 commits into from
Jul 22, 2024
Merged
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
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,22 @@ await client.attestation(async (challenge: Uint8Array) => ({
type: 'algorand', // The type of signature and public key
address: testAccount.addr, // The address of the account
signature: toBase64URL(nacl.sign.detached(challenge, testAccount.sk)), // The signature of the challenge
requestId: 12345, // Optionally authenticate a remote peer
requestId: '019097ff-bb8d-7f68-9062-89543625aca5', // Optionally authenticate a remote peer
device: 'Demo Web Wallet' // Optional device name
}))
```
#### Sign in with an existing account
```typescript
await client.assertion(
credentialId, // Some known credential ID
{requestId: 12345} // Optional requestId to link
{requestId: '019097ff-bb8d-7f68-9062-89543625aca5'} // Optional requestId to link
)
```
#### Peering with a remote client

```typescript
// Create the Peer Connection and await the remote client's answer
client.peer(12345, 'answer').then((dataChannel: RTCDataChannel)=>{
client.peer('019097ff-bb8d-7f68-9062-89543625aca5', 'answer').then((dataChannel: RTCDataChannel)=>{
// Handle the data channel
dataChannel.onmessage = (event: MessageEvent) => {
console.log(event.data)
Expand Down Expand Up @@ -82,7 +82,7 @@ interface SignalClient {
/**
* Generate a Request ID
*/
generateRequestId(): any;
generateRequestId(): string;

attestation(...args: any[]): Promise<any>;
assertion(...args: any[]): Promise<any>;
Expand All @@ -91,7 +91,7 @@ interface SignalClient {
* Top level Friendly interface for signaling
* @param args
*/
peer(requestId: any, type: 'offer' | 'answer', config?: RTCConfiguration): Promise<void>;
peer(requestId: string, type: 'offer' | 'answer', config?: RTCConfiguration): Promise<void>;

/**
* Link a Request ID to this client
Expand Down
3 changes: 2 additions & 1 deletion example/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions example/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ function handleDataChannel(dataChannel: RTCDataChannel) {
*/
async function handleOfferClient() {
// Peer to the remote client and await their offer
console.log('requestId', requestId);
client.peer(requestId, 'offer', RTC_CONFIGURATION).then(handleDataChannel)
// Once the link message is received by the remote wallet, hide the offer
client.on('link-message', () => {
Expand Down
16 changes: 15 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,14 @@
"eventemitter3": "^5.0.1",
"qr-code-styling": "*",
"socket.io-client": "^4.7.5",
"tweetnacl": "^1.0.3"
"tweetnacl": "^1.0.3",
"uuid": "^10.0.0"
},
"jest": {
"preset": "ts-jest",
"extensionsToTreatAsEsm": [".ts"],
"extensionsToTreatAsEsm": [
".ts"
],
"moduleNameMapper": {
"^(\\.{1,2}/.*)\\.js$": "$1"
},
Expand Down
24 changes: 12 additions & 12 deletions src/signal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { io, ManagerOptions, Socket, SocketOptions } from 'socket.io-client';
import QRCodeStyling, { Options as QRCodeOptions } from 'qr-code-styling';
import { EventEmitter } from 'eventemitter3';
import { attestation, DEFAULT_ATTESTATION_OPTIONS } from './attestation.js';
import { v7 as uuidv7 } from 'uuid';

export type LinkMessage = {
credId?: string;
requestId: string | number;
requestId: string;
wallet: string;
};
export const REQUEST_IS_MISSING_MESSAGE = 'Request id is required';
Expand Down Expand Up @@ -61,7 +62,7 @@ export const DEFAULT_QR_CODE_OPTIONS: QRCodeOptions = {
};

export async function generateQRCode(
{ requestId, url }: { requestId: any; url: string },
{ requestId, url }: { requestId?: string; url: string },
qrCodeOptions: QRCodeOptions = DEFAULT_QR_CODE_OPTIONS,
) {
if (typeof requestId === 'undefined')
Expand All @@ -81,11 +82,11 @@ export async function generateQRCode(
* @param {string} origin
* @param requestId
*/
export function generateDeepLink(origin: string, requestId: any) {
export function generateDeepLink(origin: string, requestId: string) {
if (typeof origin !== 'string') {
throw new Error(ORIGIN_IS_MISSING_MESSAGE);
}
if (typeof requestId === 'undefined') {
if (typeof requestId !== 'string') {
throw new Error(REQUEST_IS_MISSING_MESSAGE);
}
return `liquid://${origin.replace('https://', '')}/?requestId=${requestId}`;
Expand All @@ -97,7 +98,7 @@ export class SignalClient extends EventEmitter {
private url: string;
type: 'offer' | 'answer';
private authenticated: boolean = false;
private requestId: any | undefined;
private requestId: string | undefined;
peerClient: RTCPeerConnection | undefined;
private qrCodeOptions: QRCodeOptions = DEFAULT_QR_CODE_OPTIONS;
socket: Socket;
Expand All @@ -124,9 +125,8 @@ export class SignalClient extends EventEmitter {
});
}

static generateRequestId() {
//TODO: replace with toBase64URL(nacl.randomBytes(nacl.sign.seedLength)
return Math.random() as any;
static generateRequestId(): string {
return uuidv7()
}
attestation(
onChallenge: (challenge: Uint8Array) => any,
Expand Down Expand Up @@ -158,9 +158,9 @@ export class SignalClient extends EventEmitter {
* Create a Deep Link URI
* @param requestId
*/
deepLink(requestId: any) {
deepLink(requestId: string) {
if (
typeof requestId === 'undefined' &&
typeof requestId !== 'string' &&
typeof this.requestId === 'undefined'
) {
throw new Error(REQUEST_IS_MISSING_MESSAGE);
Expand All @@ -187,7 +187,7 @@ export class SignalClient extends EventEmitter {
* @param config
*/
async peer(
requestId: any,
requestId: string | undefined,
type: 'offer' | 'answer',
config: RTCConfiguration = {
iceServers: [
Expand Down Expand Up @@ -292,7 +292,7 @@ export class SignalClient extends EventEmitter {
* Await for a link message for a given requestId
* @param requestId
*/
async link(requestId: any) {
async link(requestId: string) {
if (typeof this.requestId !== 'undefined')
throw new Error(REQUEST_IN_PROCESS_MESSAGE);
this.requestId = requestId;
Expand Down
15 changes: 6 additions & 9 deletions test/signal.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ describe("SignalClient", function() {
// Request ID
test("generateRequestId", function() {
const id = SignalClient.generateRequestId();
expect(id).toBeGreaterThan(0);
expect(id).toBeDefined();
expect(id.length).toBe(36);
});

// TODO: Decide what to do with QR Code generation, possibly fork and maintain the library since Pera also uses it
Expand Down Expand Up @@ -267,8 +268,8 @@ describe("SignalClient", function() {
})
test("peer(answer) unbuffered", async function(){
// Only allow one peer session at a time
client.requestId = 1234
await expect(()=>client.peer(1234, "answer")).rejects.toThrow(new Error(mod.REQUEST_IN_PROCESS_MESSAGE));
client.requestId = '019097ff-bb8d-7a31-83bb-aa934d351662'
await expect(()=>client.peer('019097ff-bb8d-7a31-83bb-aa934d351662', "answer")).rejects.toThrow(new Error(mod.REQUEST_IN_PROCESS_MESSAGE));
delete client.requestId;

const sdpFixture = {
Expand Down Expand Up @@ -312,8 +313,8 @@ describe("SignalClient", function() {
})
test("peer(answer)", async function() {
// Only allow one peer session at a time
client.requestId = 1234
await expect(()=>client.peer(1234, "answer")).rejects.toThrow(new Error(mod.REQUEST_IN_PROCESS_MESSAGE));
client.requestId = '019097ff-bb8d-7a31-83bb-aa934d351662'
await expect(()=>client.peer('019097ff-bb8d-7a31-83bb-aa934d351662', "answer")).rejects.toThrow(new Error(mod.REQUEST_IN_PROCESS_MESSAGE));
delete client.requestId;

const sdpFixture = {
Expand Down Expand Up @@ -409,7 +410,6 @@ test("generateQRCode", async () => {
const qrFixture = { url: "https://liquid-auth.onrender.com", requestId: SignalClient.generateRequestId() };
expect(generateQRCode(qrFixture)).toBeDefined();
await expect(() =>
// @ts-expect-error, needed for testing
generateQRCode({ url: qrFixture.url })
).rejects.toThrow(new Error(mod.REQUEST_IS_MISSING_MESSAGE));
getRawData = () => {
Expand All @@ -430,7 +430,4 @@ test('generateDeepLink', async () => {
// @ts-expect-error, needed for testing
generateDeepLink(url)
).toThrow(new Error(REQUEST_IS_MISSING_MESSAGE));
expect(() =>
generateDeepLink(undefined, requestId)
).toThrow(new Error(ORIGIN_IS_MISSING_MESSAGE));
})
Loading