Skip to content

Commit

Permalink
Merge pull request #25 from gandalf-network/staging
Browse files Browse the repository at this point in the history
Update Readme.md
  • Loading branch information
TosinJs authored Jun 16, 2024
2 parents 8abe582 + 0624232 commit 81f38dc
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 49 deletions.
37 changes: 17 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,44 +24,37 @@ npm install @gandalf-network/connect --save

### Usage

#### Initialization
#### Import the library

```typescript
import Connect from "@gandalf-network/connect";
// Typescript && ESModules

const connect = new Connect({
publicKey: process.env.PUBLIC_KEY,
redirectURL: "YOUR_REDIRECT_URL",
services:
{
uber: {
traits: ["rating"], // At least one trait or activity is required
activities: ["trip"],
},
gandalf: {
traits: ["email"]
}
} // Only one non "Gandalf" service (e.g "netflix", "instacart") is supported per Connect URL
})
import Connect from "@gandalf-network/connect";
import { Platform } from "@gandalf-network/connect/components";
```

```javascript
// CommonJS

const Connect = require("@gandalf-network/connect");
const { Platform } = require("@gandalf-network/connect/components");
```

#### Initialize Connect

```typescript
const connect = new Connect({
publicKey: process.env.PUBLIC_KEY,
redirectURL: "YOUR_REDIRECT_URL",
// The platform defaults to IOS but could be ANDROID or UNIVERSAL
platform: Platform.ANDROID,
services:
{
uber: {
traits: ["rating"], // At least one trait or activity is required
activities: ["trip"],
},
gandalf: {
traits: ["email"]
}
} // Only one non "Gandalf" service (e.g "uber", "amazon") is supported per Connect URL
}
})
```

Expand All @@ -88,6 +81,10 @@ const datakey = Connect.getDataKeyFromURL("REDIRECT_URL")
console.log(datakey)
```

```bash
npm install @gandalf-network/connect --save
```

## Contributing

Contributions are welcome, whether they're feature requests, bug fixes, or documentation improvements.
6 changes: 4 additions & 2 deletions examples/example.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import Connect from "../src/connect";
import { ActivityType, InputData, TraitLabel } from "../src/types";
import { ActivityType, InputData, TraitLabel, Platform } from "../src/types";

const publicKey = "0x0297bb4f88a65b82c08fd20afb1259b7027dc996c8941e0c5917a452d538cd0da9";
const redirectURL = "https://example.com"
const platform = Platform.ANDROID;

const services: InputData = {
uber: {
traits: [TraitLabel.Plan],
Expand All @@ -14,7 +16,7 @@ const services: InputData = {
}

async function example() {
const connect = new Connect({publicKey, redirectURL, services})
const connect = new Connect({ publicKey, redirectURL, services, platform })

// Generate the Connect URL
const url = await connect.generateURL()
Expand Down
88 changes: 72 additions & 16 deletions src/connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ class Connect {
publicKey: string;
redirectURL: string;
data: InputData;
platform: Platform = Platform.ios;
platform: Platform = Platform.IOS;
verificationComplete: boolean = false;
useAlphaVersionParams: boolean = false;

constructor(input: ConnectInput) {
if (input.redirectURL.endsWith('/')) {
Expand All @@ -42,17 +43,29 @@ class Connect {
this.publicKey = input.publicKey;
this.redirectURL = input.redirectURL;
this.data = input.services;
this.platform = input.platform ? input.platform : Platform.ios;
this.platform = input.platform ? input.platform : Platform.IOS;
this.useAlphaVersionParams = !!input.useAlphaVersionParams;
}

async generateURL(): Promise<string> {
await this.allValidations(this.publicKey, this.redirectURL, this.data);
const data = JSON.stringify(this.data);
const appClipURL = this.encodeComponents(
data,
this.redirectURL,
this.publicKey,
);
let appClipURL = '';

if (this.useAlphaVersionParams) {
appClipURL = this.encodeLegacyComponents(
data,
this.redirectURL,
this.publicKey,
);
} else {
appClipURL = this.encodeComponents(
data,
this.redirectURL,
this.publicKey,
);
}

return appClipURL;
}

Expand Down Expand Up @@ -109,10 +122,10 @@ class Connect {
): string {
let BASE_URL = IOS_APP_CLIP_BASE_URL;
switch (this.platform) {
case Platform.android:
case Platform.ANDROID:
BASE_URL = ANDROID_APP_CLIP_BASE_URL;
break;
case Platform.universal:
case Platform.UNIVERSAL:
BASE_URL = UNIVERSAL_APP_CLIP_BASE_URL;
break;
}
Expand All @@ -132,6 +145,35 @@ class Connect {
return url.toString();
}

private encodeLegacyComponents(
services: string,
redirectUrl: string,
publicKey: string,
): string {
let BASE_URL = IOS_APP_CLIP_BASE_URL;
switch (this.platform) {
case Platform.ANDROID:
BASE_URL = ANDROID_APP_CLIP_BASE_URL;
break;
case Platform.UNIVERSAL:
BASE_URL = UNIVERSAL_APP_CLIP_BASE_URL;
break;
}

const url = new URL(BASE_URL);
const params: Record<string, string> = {
publicKey,
redirectUrl,
services,
};

Object.keys(params).forEach((key) =>
url.searchParams.append(key, params[key]),
);

return url.toString();
}

private async allValidations(
publicKey: string,
redirectURL: string,
Expand All @@ -140,7 +182,10 @@ class Connect {
if (!this.verificationComplete) {
await Connect.validatePublicKey(publicKey);
Connect.validateRedirectURL(redirectURL);
const cleanServices = await Connect.validateInputData(data);
const cleanServices = await Connect.validateInputData(
data,
this.useAlphaVersionParams,
);
this.data = cleanServices;
}

Expand All @@ -157,35 +202,46 @@ class Connect {
}
}

private static async validateInputData(input: InputData): Promise<InputData> {
private static async validateInputData(
input: InputData,
useAlphaVersionParams: boolean = false,
): Promise<InputData> {
const supportedServicesAndTraits = await getSupportedServicesAndTraits();
const cleanServices: InputData = {};

let unsupportedServices: string[] = [];

const keys = Object.keys(input).map((key) => key.toLowerCase());
const keys = Object.keys(input);
const lkeys = keys.map((key) => key.toLowerCase());

if (keys.length > 2 || (keys.length === 2 && !keys.includes('gandalf'))) {
if (
lkeys.length > 2 ||
(lkeys.length === 2 && !lkeys.includes('gandalf'))
) {
throw new GandalfError(
`Only one non Gandalf service is supported per Connect URL`,
GandalfErrorCode.InvalidService,
);
}

for (const key of keys) {
if (!supportedServicesAndTraits.services.includes(key as Source)) {
if (
!supportedServicesAndTraits.services.includes(
key.toLocaleLowerCase() as Source,
)
) {
unsupportedServices = [...unsupportedServices, key];
continue;
}

const service = input[key];
if (typeof service === 'boolean') {
if (typeof service === 'boolean' || useAlphaVersionParams) {
if (!service)
throw new GandalfError(
'At least one service has to be required',
GandalfErrorCode.InvalidService,
);
cleanServices[key.toLowerCase()] = input[key as Source];
cleanServices[key.toLowerCase()] = true;
} else {
this.validateInputService(service, supportedServicesAndTraits);
cleanServices[key.toLowerCase()] = input[key as Source];
Expand Down
7 changes: 4 additions & 3 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,17 @@ export type Service = {
};

export enum Platform {
universal = 'UNIVERSAL',
ios = 'IOS',
android = 'ANDROID',
UNIVERSAL = 'UNIVERSAL',
IOS = 'IOS',
ANDROID = 'ANDROID',
}

export type ConnectInput = {
publicKey: string;
redirectURL: string;
services: InputData;
platform?: Platform;
useAlphaVersionParams?: boolean;
};

export enum GandalfErrorCode {
Expand Down
16 changes: 8 additions & 8 deletions tests/connect.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ describe("Connect SDK", () => {

expect(connect.publicKey).toEqual(publicKey);
expect(connect.redirectURL).toEqual(redirectURL);
expect(connect.platform).toEqual(Platform.ios);
expect(connect.platform).toEqual(Platform.IOS);
});

it("should strip the redirect url of trailing slashes", async () => {
Expand All @@ -66,9 +66,9 @@ describe("Connect SDK", () => {

it("should set the platform", async () => {
const redirectURL = "https://example.com/";
const connect = new Connect({ publicKey, redirectURL, services, platform: Platform.universal });
const connect = new Connect({ publicKey, redirectURL, services, platform: Platform.UNIVERSAL });

expect(connect.platform).toEqual(Platform.universal);
expect(connect.platform).toEqual(Platform.UNIVERSAL);
});
});

Expand Down Expand Up @@ -229,15 +229,15 @@ describe("Connect SDK", () => {
});

it("should generate a universal connect URL", async () => {
const connect = new Connect({ publicKey, redirectURL, services, platform: Platform.universal });
const connect = new Connect({ publicKey, redirectURL, services, platform: Platform.UNIVERSAL });
const generatedURL = await connect.generateURL();
expect(generatedURL).toEqual(
`${UNIVERSAL_APP_CLIP_BASE_URL}/?publicKey=${encodedPublicKey}&redirectUrl=${encodedRedirectURL}&data=${encodedData}`,
);
});

it("should generate an android connect URL", async () => {
const connect = new Connect({ publicKey, redirectURL, services, platform: Platform.android });
const connect = new Connect({ publicKey, redirectURL, services, platform: Platform.ANDROID });
const generatedURL = await connect.generateURL();
expect(generatedURL).toEqual(
`${ANDROID_APP_CLIP_BASE_URL}/?publicKey=${encodedPublicKey}&redirectUrl=${encodedRedirectURL}&data=${encodedData}`,
Expand Down Expand Up @@ -305,13 +305,13 @@ describe("Connect SDK", () => {
});

it("should generate a universal connect URL", async () => {
const services = {"netflix": true};
const stringData = JSON.stringify(services);
const services = {"NETFLIX": true};
const stringData = JSON.stringify({"netflix": true});
const encodedData = encodeURIComponent(btoa(stringData));
const encodedRedirectURL = encodeURIComponent(redirectURL);
const encodedPublicKey = encodeURIComponent(publicKey);

const connect = new Connect({ publicKey, redirectURL, services, platform: Platform.universal });
const connect = new Connect({ publicKey, redirectURL, services, platform: Platform.UNIVERSAL });
const generatedURL = await connect.generateURL();
expect(generatedURL).toEqual(
`${UNIVERSAL_APP_CLIP_BASE_URL}/?publicKey=${encodedPublicKey}&redirectUrl=${encodedRedirectURL}&data=${encodedData}`,
Expand Down

0 comments on commit 81f38dc

Please sign in to comment.