Skip to content
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,5 @@ yarn-debug.log*
yarn-error.log*

.idea

CLAUDE.md
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,11 +1,11 @@
{
"name": "@dimo-network/login-with-dimo",
"version": "0.0.31",
"version": "0.0.32",
"description": "",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"test": "tsc --noEmit -p tsconfig.json",
"build": "webpack --config webpack.config.js",
"watch": "webpack --config webpack.config.js --watch"
},
Expand Down
72 changes: 72 additions & 0 deletions sdk/src/components/ShareAccountWithDimo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React from 'react';

import { EntryState, EventTypes } from '@enums/index';
import {
BaseButtonProps,
ButtonLabels,
InternalDimoActionParams,
LoginButtonProps,
} from '@dimo-types/index';
import { getPermissionsBinary } from '@utils/index';
import { useResolvedBrand, formatBrandedLabel } from '@utils/brand';
import { BaseDimoButton } from './BaseDimoButton';

type ShareAccountWithDimoProps = BaseButtonProps &
LoginButtonProps &
ButtonLabels;

const ShareAccountWithDimo: React.FC<ShareAccountWithDimoProps> = ({
mode,
onSuccess,
onError,
permissionTemplateId,
permissions,
expirationDate,
authenticatedLabel,
unAuthenticatedLabel,
utm = null,
altTitle,
brandOverride,
}) => {
const brand = useResolvedBrand(brandOverride);

const resolvedAuthLabel =
authenticatedLabel ??
formatBrandedLabel(
'Share Documents with {name}',
brand.name,
'Share Documents with DIMO'
);
const resolvedUnAuthLabel =
unAuthenticatedLabel ??
formatBrandedLabel(
'Sign in to Share Documents with {name}',
brand.name,
'Sign in to Share Documents with DIMO'
);

const payload: InternalDimoActionParams & { eventType: EventTypes } = {
permissionTemplateId,
expirationDate,
eventType: EventTypes.SHARE_ACCOUNT_DATA,
utm,
...getPermissionsBinary(permissions, permissionTemplateId),
};

return (
<BaseDimoButton
mode={mode}
entryState={EntryState.ACCOUNT_MANAGER}
onSuccess={onSuccess}
onError={onError}
buttonLabel={(authenticated) =>
authenticated ? resolvedAuthLabel : resolvedUnAuthLabel
}
altTitle={altTitle}
payload={payload}
brand={brand}
/>
);
};

export default ShareAccountWithDimo;
56 changes: 56 additions & 0 deletions sdk/src/components/__tests__/ShareAccountWithDimo.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
* Smoke test for ShareAccountWithDimo.
*
* The SDK ships no test runner (jest is an intentional no-op stub and there are
* no testing-library deps — see CLAUDE.md "No tests exist for the SDK itself").
* To stay aligned with the existing toolchain (tsc + webpack path aliases) this
* smoke test is type-checked via `npm test` (`tsc --noEmit`). It asserts that:
* 1. the component is exported from the package root,
* 2. it can be instantiated as a React element with its public props,
* 3. the SHARE_ACCOUNT_DATA event type / ACCOUNT_MANAGER entry state exist.
*/
import React from 'react';
import { DimoSDKModes, EntryState, EventTypes } from '@enums/index';
import ShareAccountWithDimo from '../ShareAccountWithDimo';
import { ShareAccountWithDimo as ShareAccountWithDimoFromRoot } from '../../index';

// 1. Exported from the package root.
console.assert(
ShareAccountWithDimoFromRoot === ShareAccountWithDimo,
'ShareAccountWithDimo should be re-exported from the package root'
);

// 2. Renders / mounts as a valid React element with its public props.
const element = (
<ShareAccountWithDimo
mode={DimoSDKModes.POPUP}
permissions={[]}
permissionTemplateId="1"
expirationDate="2027-01-01T00:00:00Z"
onSuccess={(authData) => {
// accountGranted + transactionHash are surfaced on success.
void authData.accountGranted;
void authData.transactionHash;
void authData.token;
}}
onError={(e) => console.error(e)}
brandOverride={{ name: 'Acme' }}
/>
);

console.assert(
React.isValidElement(element),
'ShareAccountWithDimo should produce a valid React element'
);

// 3. The enum members the component relies on exist.
console.assert(
EventTypes.SHARE_ACCOUNT_DATA === 'SHARE_ACCOUNT_DATA',
'SHARE_ACCOUNT_DATA event type should exist'
);
console.assert(
EntryState.ACCOUNT_MANAGER === 'ACCOUNT_MANAGER',
'ACCOUNT_MANAGER entry state should exist'
);

export {};
1 change: 1 addition & 0 deletions sdk/src/enums/auth.enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export enum EntryState {
OTP_INPUT = 'OTP_INPUT',
SUCCESS = 'SUCCESS',
VEHICLE_MANAGER = 'VEHICLE_MANAGER',
ACCOUNT_MANAGER = 'ACCOUNT_MANAGER',
ADVANCED_TRANSACTION = 'ADVANCED_TRANSACTION',
SIGN_MESSAGE = 'SIGN_MESSAGE',
ERROR = 'ERROR',
Expand Down
1 change: 1 addition & 0 deletions sdk/src/enums/events.enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export enum MessageEventType {
export enum EventTypes {
EXECUTE_ADVANCED_TRANSACTION = 'EXECUTE_ADVANCED_TRANSACTION',
SHARE_VEHICLES_DATA = 'SHARE_VEHICLES_DATA',
SHARE_ACCOUNT_DATA = 'SHARE_ACCOUNT_DATA',
SIGN_MESSAGE = 'SIGN_MESSAGE',
LOGOUT = 'LOGOUT',
}
1 change: 1 addition & 0 deletions sdk/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Export components
export { default as LoginWithDimo } from './components/LoginWithDimo';
export { default as ShareVehiclesWithDimo } from './components/ShareVehiclesWithDimo';
export { default as ShareAccountWithDimo } from './components/ShareAccountWithDimo';
export { default as ExecuteAdvancedTransactionWithDimo } from './components/ExecuteAdvancedTransactionWithDimo';
export { default as SignMessageWithDimo } from './components/SignMessageWithDimo';
export { default as LogoutWithDimo } from './components/LogoutWithDimo';
Expand Down
1 change: 1 addition & 0 deletions sdk/src/types/common.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export interface AuthData {
transactionHash?: string;
transactionReceipt?: TransactionReceipt;
sharedVehicles?: string[];
accountGranted?: boolean;
signature?: `0x${string}`;
signer?: `0x${string}`;
}
Expand Down
1 change: 1 addition & 0 deletions sdk/src/types/events.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export interface MessageData {
transactionHash?: string;
transactionReceipt?: TransactionReceipt;
sharedVehicles?: string[];
accountGranted?: boolean;
message?: string;
signature?: `0x${string}`;
signer?: `0x${string}`;
Expand Down
14 changes: 11 additions & 3 deletions sdk/src/utils/authUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@ import {
} from '@storage/storageManager';

export const processAuthResponse = (
{ token, walletAddress, email, sharedVehicles }: any,
{ token, walletAddress, email, sharedVehicles, accountGranted }: any,
setAuthenticated: (status: boolean) => void,
onSuccess: (data: { token: string; sharedVehicles: string[] }) => void
onSuccess: (data: {
token: string;
sharedVehicles: string[];
accountGranted?: boolean;
}) => void
) => {
// This auth response may be triggered for a coupled or decoupled flow
// If decoupled, it will only return token
Expand All @@ -18,7 +22,11 @@ export const processAuthResponse = (
if (token) {
storeJWTInCookies(token);
setAuthenticated(true);
onSuccess({ token, sharedVehicles });
onSuccess({
token,
sharedVehicles,
...(accountGranted !== undefined && { accountGranted }),
});
}
};

Expand Down
10 changes: 7 additions & 3 deletions sdk/src/utils/eventHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,19 +74,20 @@ const handleAuthResponse = (
};

const handleTransactionResponse = (
{ token, transactionHash, transactionReceipt }: MessageData,
{ token, transactionHash, transactionReceipt, accountGranted }: MessageData,
handlers: EventHandlers
): void => {
if (!token) {
handlers.onError(new Error('Missing authentication token'));
return;
}

if (transactionHash || transactionReceipt) {
if (transactionHash || transactionReceipt || accountGranted) {
const responseData: AuthData = {
token: token,
...(transactionHash && { transactionHash }),
...(transactionReceipt && { transactionReceipt }),
...(accountGranted !== undefined && { accountGranted }),
};
handlers.onSuccess(responseData);
} else {
Expand Down Expand Up @@ -189,7 +190,10 @@ export const createMessageHandler = (
messageData,
{ onSuccess, onError, setAuthenticated },
mode === DimoSDKModes.POPUP
? { sharedVehicles: messageData.sharedVehicles }
? {
sharedVehicles: messageData.sharedVehicles,
accountGranted: messageData.accountGranted,
}
: {}
);
};
Expand Down