Skip to content

Commit

Permalink
Merge pull request #61 from DIMO-Network/development
Browse files Browse the repository at this point in the history
v0.0.19 (Refactor + UTM Support)
  • Loading branch information
MoizAhmedd authored Feb 26, 2025
2 parents 2b095fc + 67d4c44 commit ec402c4
Show file tree
Hide file tree
Showing 22 changed files with 1,078 additions and 865 deletions.
Binary file not shown.
Binary file not shown.
1,534 changes: 810 additions & 724 deletions example-dimo-auth/package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions example-dimo-auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@dimo-network/login-with-dimo": "file:./dimo-network-login-with-dimo-0.0.18.tgz",
"@dimo-network/login-with-dimo": "file:./dimo-network-login-with-dimo-0.0.19.tgz",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
Expand Down Expand Up @@ -50,4 +50,4 @@
"prettier": "3.5.1",
"typescript-eslint": "^8.24.1"
}
}
}
6 changes: 4 additions & 2 deletions example-dimo-auth/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ import { sampleAbi } from './abi/sample-abi';
function App() {
const [permissionsEnabled, setPermissionsEnabled] = useState(false);
const [forceEmail, setForceEmail] = useState(false);
const { isAuthenticated, email, walletAddress } =
useDimoAuthState();
const { isAuthenticated, email, walletAddress } = useDimoAuthState();

const sampleExpirationDate = new Date(Date.UTC(2025, 11, 11, 18, 51)); // Note: Month is zero-based

Expand Down Expand Up @@ -75,6 +74,8 @@ function App() {
onError={(error: any) => console.error('Error:', error)}
permissionTemplateId={permissionsEnabled ? '2' : undefined}
unAuthenticatedLabel="Sign In with DIMO"
utm="MOIZ"
// Optionally, specify vehicles (uncomment the line below to use it)
// vehicles={["752", "742", "738", "722"]}
// vehicles={["585","586"]}
/>
Expand Down Expand Up @@ -114,6 +115,7 @@ function App() {
onSuccess={(authData: any) => console.log('Success:', authData)}
onError={(error: any) => console.error('Error:', error)}
permissionTemplateId={permissionsEnabled ? '1' : undefined}
utm="dimo"
/>

{isAuthenticated && (
Expand Down
63 changes: 57 additions & 6 deletions sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,9 @@ Based on this authenticated state, you can render the necessary Dimo components

With the DIMO SDK, developers have the ability to control how their users interact with DIMO.

We offer three options

We offer two options
- Popup Mode (best for allowing users to see both the app, as well as DIMO)
- Embed Mode (best for keeping the dimo login within a developers app)
- NOTE: Apple SSO will not work in Embed Mode
- Redirect Mode (best for developers that want to avoid popups, or embedding)
- Redirect Mode (best for developers that want to avoid popups)

### Using the Button Components

Expand All @@ -99,6 +96,7 @@ import {
onSuccess={(authData) => console.log("Success:", authData)}
onError={(error) => console.error("Error:", error)}
permissionTemplateId={permissionsEnabled ? "1" : undefined} //This will control if your users are asked to share vehicles, as part of the login flow. "1" is the template for all SACD permissions
utm="utm_campaign=dimo"
// Optionally, specify vehicles (uncomment the line below to use it)
// vehicles={["585","586"]} // Specify the vehicles to be accessed after login
/>
Expand Down Expand Up @@ -134,7 +132,7 @@ In many cases - developers may want to couple/decouple usage of these components
A common flow is

1. Show the login button, when in authenticated
2. Show the Share Vehicles and Execute Advanced Transaction button, when authenticed
2. Show the Share Vehicles and Execute Advanced Transaction button, when authenticated

This can be achieved by simply wrapping those buttons in a conditional as follows, to create a full example as follows

Expand Down Expand Up @@ -197,3 +195,56 @@ initializeDimoSDK({
/>
)}
```

## Component Descriptions and Parameters

### LoginWithDimo

The `LoginWithDimo` component allows users to authenticate with DIMO.

| Parameter | Description | Default Value | Type | Mandatory |
|-----------------------|-----------------------------------------------------------------------------|------------------------------|--------------------------------|-----------|
| `mode` | Mode of the button (`popup`, `redirect`) | N/A | `"popup" \| "redirect"` | Yes |
| `onSuccess` | Callback function to handle success | N/A | `(authData: AuthData) => void` | Yes |
| `onError` | Callback function to handle errors | N/A | `(error: Error) => void` | Yes |
| `permissionTemplateId`| Permissions template ID | `undefined` | `string` | No |
| `vehicles` | List of vehicles | `undefined` | `string[]` | No |
| `vehicleMakes` | List of vehicle makes | `undefined` | `string[]` | No |
| `expirationDate` | Expiration date for permissions | `undefined` | `string` | No |
| `authenticatedLabel` | Label when the user is authenticated | `"Manage DIMO Account"` | `string` | No |
| `unAuthenticatedLabel`| Label when the user is not authenticated | `"Continue with DIMO"` | `string` | No |
| `utm` | UTM parameters for tracking (a query string) | `null` | `string` | No |

### ShareVehiclesWithDimo

The `ShareVehiclesWithDimo` component allows users to share their vehicles data with DIMO.

| Parameter | Description | Default Value | Type | Mandatory |
|-----------------------|-----------------------------------------------------------------------------|-----------------------------------------|--------------------------------|-----------|
| `mode` | Mode of the button (`popup`, `redirect`) | N/A | `"popup" \| "redirect"` | Yes |
| `onSuccess` | Callback function to handle success | N/A | `(authData: AuthData) => void` | Yes |
| `onError` | Callback function to handle errors | N/A | `(error: Error) => void` | Yes |
| `permissionTemplateId`| Permissions template ID | N/A | `string` | Yes |
| `vehicles` | List of vehicles | `undefined` | `string[]` | No |
| `vehicleMakes` | List of vehicle makes | `undefined` | `string[]` | No |
| `expirationDate` | Expiration date for permissions | `undefined` | `string` | No |
| `authenticatedLabel` | Label when the user is authenticated | `"Share Vehicles with DIMO"` | `string` | No |
| `unAuthenticatedLabel`| Label when the user is not authenticated | `"Sign in to Share Vehicles with DIMO"` | `string` | No |
| `utm` | UTM parameters for tracking (a query string) | `null` | `string` | No |

### ExecuteAdvancedTransactionWithDimo

The `ExecuteAdvancedTransactionWithDimo` component allows users to execute advanced web3 transactions with DIMO.

| Parameter | Description | Default Value | Type | Mandatory |
|-----------------------|-----------------------------------------------------------------------------|----------------------------------------------|----------------------------------|-----------|
| `mode` | Mode of the button (`popup`, `redirect`) | N/A | `"popup" \| "redirect"` | Yes |
| `onSuccess` | Callback function to handle success | N/A | `(transactionData: any) => void` | Yes |
| `onError` | Callback function to handle errors | N/A | `(error: Error) => void` | Yes |
| `address` | Address for the transaction | N/A | `string` | Yes |
| `value` | Value for the transaction | `""` | `string` | No |
| `abi` | ABI for the transaction | N/A | `any` | Yes |
| `functionName` | Function name for the transaction | N/A | `string` | Yes |
| `args` | Arguments for the transaction | N/A | `string[]` | Yes |
| `authenticatedLabel` | Label when the user is authenticated | `"Execute Advanced Transaction with Dimo"` | `string` | No |
| `unAuthenticatedLabel`| Label when the user is not authenticated | `"Sign in to Execute Transaction"` | `string` | No |
4 changes: 2 additions & 2 deletions sdk/package-lock.json

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

4 changes: 2 additions & 2 deletions sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dimo-network/login-with-dimo",
"version": "0.0.18",
"version": "0.0.19",
"description": "",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down Expand Up @@ -34,4 +34,4 @@
"webpack": "^5.64.4",
"webpack-cli": "^4.9.1"
}
}
}
2 changes: 1 addition & 1 deletion sdk/src/auth/embedAuth.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BasePayload } from '@dimo-types/BasePayload';
import { BasePayload } from '@dimo-types/index';
import { handleMessageForEmbed } from '@utils/eventHandler';

export const embedAuth = (
Expand Down
4 changes: 2 additions & 2 deletions sdk/src/auth/popupAuth.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { BasePayload } from '@dimo-types/BasePayload';
import { BasePayload, DimoActionPayload } from '@dimo-types/index';
import { handleMessageForPopup } from '@utils/eventHandler';

export const popupAuth = (
basePayload: BasePayload,
data?: Record<string, any> // Component-specific data
data?: DimoActionPayload // Component-specific data
) => {
try {
const { dimoLogin } = basePayload;
Expand Down
107 changes: 64 additions & 43 deletions sdk/src/auth/redirectAuth.ts
Original file line number Diff line number Diff line change
@@ -1,58 +1,79 @@
import { BasePayload } from '@dimo-types/BasePayload';
import {
BasePayload,
BasePayloadParams,
TransactionData,
DimoActionPayload,
} from '@dimo-types/index';

export const redirectAuth = (payload: BasePayload, data?: any) => {
//TODO: Can probably be cleaned up to prevent having to manually parse out everything
type RedirectAuthData = BasePayloadParams & DimoActionPayload;

const { clientId, redirectUri, entryState, dimoLogin, forceEmail } = payload;
const appendParams = (
params: URLSearchParams,
key: string,
value: RedirectAuthData[keyof RedirectAuthData]
) => {
if (value) {
if (Array.isArray(value)) {
value.forEach((item) => params.append(key, item));
} else {
params.append(key, String(value));
}
}
};

const {
permissionTemplateId,
vehicles,
vehicleMakes,
expirationDate,
transactionData,
} = data;
const addParams = (
data: RedirectAuthData,
params: URLSearchParams,
paramsToAdd: Array<keyof RedirectAuthData>
) => {
paramsToAdd.forEach((param) => {
appendParams(params, param, data[param]);
});
};

const params = new URLSearchParams();
const transformTransactionData = (
transactionData: TransactionData | string | undefined
) => {
if (!transactionData) return undefined;
if (typeof transactionData === 'string') return transactionData;

if (clientId) params.append('clientId', clientId);
if (redirectUri) params.append('redirectUri', redirectUri);
if (permissionTemplateId)
params.append('permissionTemplateId', permissionTemplateId);
if (entryState) params.append('entryState', entryState);
if (vehicles && vehicles.length > 0) {
vehicles.forEach((vehicle: string) => params.append('vehicles', vehicle));
}
const serializedTransactionData = encodeURIComponent(
JSON.stringify(transactionData)
);

if (vehicleMakes && vehicleMakes.length > 0) {
vehicleMakes.forEach((vehicleMake: string) =>
params.append('vehicleMakes', vehicleMake)
if (serializedTransactionData.length > 1000) {
console.warn(
'Serialized transactionData is too large for a URL parameter.'
);
return undefined;
}

if (expirationDate) {
params.append('expirationDate', expirationDate);
}
return serializedTransactionData;
};

// Serialize and encode transactionData
if (transactionData) {
const serializedTransactionData = encodeURIComponent(
JSON.stringify(transactionData)
);
export const redirectAuth = (payload: BasePayload, data: DimoActionPayload) => {
const { dimoLogin } = payload;

if (serializedTransactionData.length > 1000) {
console.warn(
'Serialized transactionData is too large for a URL parameter.'
);
} else {
params.append('transactionData', serializedTransactionData);
}
}
const baseData: RedirectAuthData = {
...payload,
...data,
transactionData: transformTransactionData(data.transactionData),
};

// Use forceEmail from payload
if (forceEmail) {
params.append('forceEmail', 'true');
}
const params = new URLSearchParams();

addParams(baseData, params, [
'clientId',
'entryState',
'expirationDate',
'forceEmail',
'permissionTemplateId',
'redirectUri',
'transactionData',
'utm',
'vehicleMakes',
'vehicles',
]);

// Construct the full URL
window.location.href = `${dimoLogin}?${params.toString()}`;
Expand Down
34 changes: 18 additions & 16 deletions sdk/src/components/BaseDimoButton.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,34 @@
import React from 'react';
import React, { type FC } from 'react';

import { popupAuth } from '@auth/popupAuth';
import { embedAuth } from '@auth/embedAuth';
import { redirectAuth } from '@auth/redirectAuth';
import { getDimoConfig } from '../config/sdkConfig';
import { EntryState } from '@enums/globalEnums';
import { EntryState, EventTypes } from '@enums/index';
import '../styles/BaseDimoButton.css';
import {
DimoAuthProvider,
useDimoAuthState,
useDimoAuthUpdater,
} from '@auth/context/DimoAuthContext';
import { LoginMode } from '@dimo-types/LoginMode';
} from '../auth/context/DimoAuthContext';
import {
BaseButtonProps,
BaseLoginButtonProps,
BasePayload,
DimoActionPayload,
} from '@dimo-types/index';

interface BaseDimoButtonProps {
mode: LoginMode;
entryState: EntryState;
onSuccess: (data: {
token: string;
transactionHash?: string;
transactionReceipt?: any;
}) => void; // Success callback
onError: (error: Error) => void; // Error callback
interface BaseDimoButtonOptions extends BaseButtonProps {
buttonLabel: (authenticated: boolean) => string; // Function to determine button label dynamically
entryState: EntryState;
disableIfAuthenticated?: boolean; // Disable button if authenticated (default: false)
payload: Record<string, any>; // Dynamic payload object
payload: DimoActionPayload
}

const BaseDimoButton: React.FC<BaseDimoButtonProps> = ({
type BaseDimoButtonProps = BaseDimoButtonOptions &
(BaseLoginButtonProps | object);

const BaseDimoButton: FC<BaseDimoButtonProps> = ({
mode,
entryState,
onSuccess,
Expand All @@ -47,7 +49,7 @@ const BaseDimoButton: React.FC<BaseDimoButtonProps> = ({
? 'https://login.dev.dimo.org'
: 'https://login.dimo.org';

const basePayload = {
const basePayload: BasePayload = {
entryState,
onSuccess,
onError,
Expand Down
Loading

0 comments on commit ec402c4

Please sign in to comment.