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
65 changes: 53 additions & 12 deletions packages/smart-accounts-kit/src/caveatBuilder/scope/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,16 @@ import {
import { ScopeType } from '../../constants';
import type { SmartAccountsEnvironment } from '../../types';

export type ScopeConfig =
// We want to allow the scope `type` to be passed as either an enum reference,
// or the enum's string value this generic accepts a union of scope configs, and
// converts them to an identical union except the `type` parameter is converted
// to a union of `ScopeType.XXXX | `${ScopeType.XXXX}`.
export type ConvertScopeConfigsToInputs<T extends { type: ScopeType }> =
T extends { type: ScopeType }
? Omit<T, 'type'> & { type: T['type'] | `${T['type']}` }
: never;

type ScopeConfigBase =
| Erc20TransferScopeConfig
| Erc20StreamingScopeConfig
| Erc20PeriodicScopeConfig
Expand All @@ -48,32 +57,64 @@ export type ScopeConfig =
| OwnershipScopeConfig
| FunctionCallScopeConfig;

export type ScopeConfig = ConvertScopeConfigsToInputs<ScopeConfigBase>;

const normalizeScopeConfig = (config: ScopeConfig): ScopeConfigBase => {
return {
...config,
type: config.type as ScopeType,
} as ScopeConfigBase;
};

export const createCaveatBuilderFromScope = (
environment: SmartAccountsEnvironment,
scopeConfig: ScopeConfig,
) => {
switch (scopeConfig.type) {
const normalizedScopeConfig = normalizeScopeConfig(scopeConfig);

switch (normalizedScopeConfig.type) {
case ScopeType.Erc20TransferAmount:
return createErc20TransferCaveatBuilder(environment, scopeConfig);
return createErc20TransferCaveatBuilder(
environment,
normalizedScopeConfig,
);
case ScopeType.Erc20Streaming:
return createErc20StreamingCaveatBuilder(environment, scopeConfig);
return createErc20StreamingCaveatBuilder(
environment,
normalizedScopeConfig,
);
case ScopeType.Erc20PeriodTransfer:
return createErc20PeriodicCaveatBuilder(environment, scopeConfig);
return createErc20PeriodicCaveatBuilder(
environment,
normalizedScopeConfig,
);
case ScopeType.NativeTokenTransferAmount:
return createNativeTokenTransferCaveatBuilder(environment, scopeConfig);
return createNativeTokenTransferCaveatBuilder(
environment,
normalizedScopeConfig,
);
case ScopeType.NativeTokenStreaming:
return createNativeTokenStreamingCaveatBuilder(environment, scopeConfig);
return createNativeTokenStreamingCaveatBuilder(
environment,
normalizedScopeConfig,
);
case ScopeType.NativeTokenPeriodTransfer:
return createNativeTokenPeriodicCaveatBuilder(environment, scopeConfig);
return createNativeTokenPeriodicCaveatBuilder(
environment,
normalizedScopeConfig,
);
case ScopeType.Erc721Transfer:
return createErc721CaveatBuilder(environment, scopeConfig);
return createErc721CaveatBuilder(environment, normalizedScopeConfig);
case ScopeType.OwnershipTransfer:
return createOwnershipCaveatBuilder(environment, scopeConfig);
return createOwnershipCaveatBuilder(environment, normalizedScopeConfig);
case ScopeType.FunctionCall:
return createFunctionCallCaveatBuilder(environment, scopeConfig);
return createFunctionCallCaveatBuilder(
environment,
normalizedScopeConfig,
);
default:
// eslint-disable-next-line no-case-declarations
const exhaustivenessCheck: never = scopeConfig;
const exhaustivenessCheck: never = normalizedScopeConfig;
throw new Error(
`Invalid scope type: ${(exhaustivenessCheck as { type: string }).type}`,
);
Expand Down
22 changes: 20 additions & 2 deletions packages/smart-accounts-kit/test/delegation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,24 @@ describe('resolveAuthority', () => {
});

describe('createDelegation', () => {
it('creates a delegation with a scope type as a string', () => {
const result = createDelegation({
environment: smartAccountEnvironment,
scope: { ...erc20Scope, type: 'erc20TransferAmount' },
to: mockDelegate,
from: mockDelegator,
});

expect(result).to.deep.equal({
delegate: mockDelegate,
delegator: mockDelegator,
authority: ROOT_AUTHORITY,
caveats: [...erc20ScopeCaveats],
salt: '0x',
signature: '0x',
});
});

it('should create a basic delegation with root authority', () => {
const result = createDelegation({
environment: smartAccountEnvironment,
Expand All @@ -178,9 +196,9 @@ describe('createDelegation', () => {
expect(result).to.deep.equal({
delegate: mockDelegate,
delegator: mockDelegator,
authority: ROOT_AUTHORITY as Hex,
authority: ROOT_AUTHORITY,
caveats: [...erc20ScopeCaveats, mockCaveat],
salt: '0x' as Hex,
salt: '0x',
signature: '0x',
});
});
Expand Down
Loading