Skip to content

Commit

Permalink
fix: rename networkType param and set default
Browse files Browse the repository at this point in the history
  • Loading branch information
ErnoW committed Sep 29, 2022
1 parent a0e9dcb commit 4289372
Show file tree
Hide file tree
Showing 30 changed files with 869 additions and 85 deletions.
7 changes: 7 additions & 0 deletions .changeset/pretty-mayflies-add.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@moralisweb3/auth': patch
'@moralisweb3/evm-utils': patch
'@moralisweb3/streams': patch
---

Rename `network` param to `networkType` for `Moralis.Streams` and `Moralis.Auth`, to communicate more clearly the purpose of this param. Also make this value optional and default to `"evm"`
44 changes: 29 additions & 15 deletions packages/auth/src/methods/requestMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import MoralisCore, { AuthErrorCode, MoralisAuthError } from '@moralisweb3/core'
import { EvmAddress, EvmAddressish, EvmChain, EvmChainish } from '@moralisweb3/evm-utils';
import { BASE_URL } from '../MoralisAuth';
import { initializeChallengeEvm, initializeChallengeSol } from '../resolvers';

export enum AuthNetwork {
EVM = 'evm',
SOLANA = 'solana',
}
import { AuthNetworkType } from '../utils/AuthNetworkType';

// Imported from Swagger and adjusted for better types for Evm
// TODO: generalize and extend generated types
export interface RequestMessageEvmOptions {
network: 'evm';
networkType?: 'evm';
/**
* @deprecared use networkType instead
*/
network?: 'evm';
domain: string;
chain: EvmChainish;
address: EvmAddressish;
Expand All @@ -26,9 +26,12 @@ export interface RequestMessageEvmOptions {
resources?: string[];
timeout: number;
}

export interface RequestMessageSolOptions {
network: 'solana';
networkType: 'solana';
/**
* @deprecared use networkType instead
*/
network?: 'solana';
domain: string;
solNetwork: SolNetworkish;
address: SolAddressish;
Expand All @@ -46,7 +49,7 @@ export type RequestMessageOptions = RequestMessageEvmOptions | RequestMessageSol

const makeEvmRequestMessage = (
core: MoralisCore,
{ chain, address, network, ...options }: RequestMessageEvmOptions,
{ chain, address, networkType, network, ...options }: RequestMessageEvmOptions,
) => {
return EndpointResolver.create(core, BASE_URL, initializeChallengeEvm).fetch({
chainId: EvmChain.create(chain).apiId,
Expand All @@ -57,7 +60,7 @@ const makeEvmRequestMessage = (

const makeSolRequestMessage = (
core: MoralisCore,
{ address, solNetwork, network, ...options }: RequestMessageSolOptions,
{ address, solNetwork, networkType, network, ...options }: RequestMessageSolOptions,
) => {
return EndpointResolver.create(core, BASE_URL, initializeChallengeSol).fetch({
network: SolNetwork.create(solNetwork).network,
Expand All @@ -66,16 +69,27 @@ const makeSolRequestMessage = (
});
};

export const makeRequestMessage = (core: MoralisCore) => (options: RequestMessageOptions) => {
switch (options.network) {
case AuthNetwork.EVM:
export const makeRequestMessage = (core: MoralisCore) => async (options: RequestMessageOptions) => {
// Backwards compatibility for the 'network' parameter
if (!options.networkType && options.network) {
options.networkType = options.network;
}

switch (options.networkType) {
case AuthNetworkType.EVM:
return makeEvmRequestMessage(core, options);
case AuthNetwork.SOLANA:
case AuthNetworkType.SOLANA:
return makeSolRequestMessage(core, options);
default:
if (!options.networkType) {
return makeEvmRequestMessage(core, options);
}

throw new MoralisAuthError({
code: AuthErrorCode.INCORRECT_NETWORK,
message: `Incorrect network provided. Got "${options.network}", Valid values are: ${Object.values(AuthNetwork)
message: `Incorrect network provided. Got "${options.networkType}", Valid values are: ${Object.values(
AuthNetworkType,
)
.map((value) => `"${value}"`)
.join(', ')}`,
});
Expand Down
39 changes: 29 additions & 10 deletions packages/auth/src/methods/verify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,68 @@ import { EndpointResolver } from '@moralisweb3/api-utils';
import MoralisCore, { AuthErrorCode, MoralisAuthError } from '@moralisweb3/core';
import { BASE_URL } from '../MoralisAuth';
import { completeChallengeEvm, completeChallengeSol } from '../resolvers';
import { AuthNetwork } from './requestMessage';
import { AuthNetworkType } from '../utils/AuthNetworkType';

export interface VerifyEvmOptions {
networkType?: 'evm';
/**
* @deprecared use networkType instead
*/
network?: 'evm';
message: string;
signature: string;
network: 'evm';
}

export interface VerifySolOptions {
networkType: 'solana';
/**
* @deprecared use networkType instead
*/
network?: 'solana';
message: string;
signature: string;
network: 'solana';
}

export type VerifyOptions = VerifyEvmOptions | VerifySolOptions;

export type VerifyEvmData = ReturnType<typeof makeEvmVerify>;
export type VerifySolData = ReturnType<typeof makeSolVerify>;

const makeEvmVerify = (core: MoralisCore, { network, ...options }: VerifyEvmOptions) => {
const makeEvmVerify = (core: MoralisCore, { networkType, network, ...options }: VerifyEvmOptions) => {
return EndpointResolver.create(core, BASE_URL, completeChallengeEvm).fetch({
message: options.message,
signature: options.signature,
});
};

const makeSolVerify = (core: MoralisCore, { network, ...options }: VerifySolOptions) => {
const makeSolVerify = (core: MoralisCore, { networkType, network, ...options }: VerifySolOptions) => {
return EndpointResolver.create(core, BASE_URL, completeChallengeSol).fetch({
message: options.message,
signature: options.signature,
});
};

export const makeVerify = (core: MoralisCore) => (options: VerifyOptions) => {
switch (options.network) {
case AuthNetwork.EVM:
export const makeVerify = (core: MoralisCore) => async (options: VerifyOptions) => {
// Backwards compatibility for the 'network' parameter
if (!options.networkType && options.network) {
options.networkType = options.network;
}

switch (options.networkType) {
case AuthNetworkType.EVM:
return makeEvmVerify(core, options);
case AuthNetwork.SOLANA:
case AuthNetworkType.SOLANA:
return makeSolVerify(core, options);
default:
if (!options.networkType) {
return makeEvmVerify(core, options);
}

throw new MoralisAuthError({
code: AuthErrorCode.INCORRECT_NETWORK,
message: `Incorrect network provided. Got "${options.network}", Valid values are: ${Object.values(AuthNetwork)
message: `Incorrect network provided. Got "${options.networkType}", Valid values are: ${Object.values(
AuthNetworkType,
)
.map((value) => `"${value}"`)
.join(', ')}`,
});
Expand Down
4 changes: 4 additions & 0 deletions packages/auth/src/utils/AuthNetworkType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum AuthNetworkType {
EVM = 'evm',
SOLANA = 'solana',
}
10 changes: 9 additions & 1 deletion packages/evmUtils/src/dataTypes/EvmChain/EvmChain.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ describe('EvmChain', () => {
expect(chain.apiHex).toBe('0x2d');
});

it('should create a new EvmChain based on a decimal-string', () => {
const chain = EvmChain.create("45")

expect(chain.format()).toBe('0x2d');
expect(chain.decimal).toBe(45);
expect(chain.apiHex).toBe('0x2d');
});

it('should throw an error when creating a chain with unknown name', () => {
expect(() => EvmChain.create('bitcoin')).toThrowErrorMatchingInlineSnapshot(
`"[C0005] Invalid provided chain, value must be a positive number, or a hex-string starting with '0x'"`,
Expand All @@ -51,7 +59,7 @@ describe('EvmChain', () => {

it('should throw an error when creating 0', () => {
expect(() => EvmChain.create(0)).toThrowErrorMatchingInlineSnapshot(
`"[C0005] Invalid provided chain, value must be a positive number, chain-name or a hex-string starting with '0x'"`,
`"[C0005] Invalid provided chain, value must be a positive number, or a hex-string starting with '0x'"`,
);
});

Expand Down
30 changes: 23 additions & 7 deletions packages/evmUtils/src/dataTypes/EvmChain/EvmChainParser.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,40 @@
import { CoreErrorCode, MoralisCoreError } from '@moralisweb3/core';
import { InputChainId } from './EvmChainish';

const INVALID_VALUES = ['0x', '0x0', '0', 0];

export class EvmChainParser {
public static parse(chain: InputChainId): string {
if (typeof chain === 'string') {
if (chain.startsWith('0x') && chain !== '0x' && chain !== '0x0') {
return chain;
}

if (INVALID_VALUES.includes(chain)) {
throw new MoralisCoreError({
code: CoreErrorCode.INVALID_ARGUMENT,
message: "Invalid provided chain, value must be a positive number, or a hex-string starting with '0x'",
});
}

if (typeof chain === 'string') {
if (chain.startsWith('0x')) {
return chain;
}

try {
const parsed = parseInt(chain, 10);
if (Number.isNaN(parsed)) {
throw new Error('Cannot parse the provided string value to a valid chain number');
}
return `0x${parsed.toString(16)}`;
} catch (error) {
throw new MoralisCoreError({
code: CoreErrorCode.INVALID_ARGUMENT,
message: "Invalid provided chain, value must be a positive number, or a hex-string starting with '0x'",
});
}
}

if (chain <= 0) {
throw new MoralisCoreError({
code: CoreErrorCode.INVALID_ARGUMENT,
message:
"Invalid provided chain, value must be a positive number, chain-name or a hex-string starting with '0x'",
message: "Invalid provided chain, value must be a positive number, or a hex-string starting with '0x'",
});
}
return `0x${chain.toString(16)}`;
Expand Down
50 changes: 50 additions & 0 deletions packages/integration/mockRequests/authApi/evmRequestChallenge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { rest } from 'msw';
import { AUTH_API_ROOT, MOCK_API_KEY } from '../config';

const MockResponse: Record<string, { data: any; status: number }> = {
VALID_RESPONSE: {
data: {
id: 'x8yok3wHhgfAOCfPx',
message:
'defi.finance wants you to sign in with your Ethereum account:\n0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B\n\n\nURI: https://defi.finance/\nVersion: 1\nChain ID: 1\nNonce: 984ge9Yuc9gLTMEJO\nIssued At: 2022-09-29T13:10:23.832Z',
profileId: '0xed330cc4d7da53313bc7480dcdfcb876c05b94926e6156e3bd8667c0c542277b',
},
status: 201,
},
INVALID_ADDRESS: {
data: {
statusCode: 400,
name: 'BadRequestException',
message: ['address must be an Ethereum address'],
},
status: 400,
},
MULTI_ERROR: {
data: {
statusCode: 400,
name: 'BadRequestException',
message: ['domain must be a valid domain name', 'address must be an Ethereum address'],
},
status: 400,
},
};

export const mockEvmRequestChallenge = rest.post(`${AUTH_API_ROOT}/challenge/request/evm`, (req, res, ctx) => {
const apiKey = req.headers.get('x-api-key');
const id = (req.body as Record<string, any>).statement as string;

if (apiKey !== MOCK_API_KEY) {
return res(
ctx.status(401),
ctx.json({
message: 'Api Key Not Present',
}),
);
}

if (MockResponse[id]) {
return res(ctx.status(MockResponse[id].status), ctx.json(MockResponse[id].data));
}

throw new Error('mockEvmRequestChallenge: Not supported scenario');
});
60 changes: 60 additions & 0 deletions packages/integration/mockRequests/authApi/evmVerify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { rest } from 'msw';
import { AUTH_API_ROOT, MOCK_API_KEY } from '../config';

const MockResponse: Record<string, { data: any; status: number }> = {
VALID_RESPONSE: {
data: {
id: 'fRyt67D3eRss3RrX',
domain: 'defi.finance',
chainId: '1',
address: '0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B',
statement: 'Please confirm',
uri: 'https://defi.finance/',
expirationTime: '2020-01-01T00:00:00.000Z',
notBefore: '2020-01-01T00:00:00.000Z',
resources: ['https://docs.moralis.io/'],
version: '1.0',
nonce: '0x1234567890abcdef0123456789abcdef1234567890abcdef',
profileId: '0xbfbcfab169c67072ff418133124480fea02175f1402aaa497daa4fd09026b0e1',
},
status: 201,
},

INVALID_SIGNATURE: {
data: {
statusCode: 400,
name: 'BadRequestException',
message: 'Invalid Signature',
},
status: 400,
},

MULTI_ERROR: {
data: {
statusCode: 400,
name: 'BadRequestException',
message: ['message must be present', 'signature must be present'],
},
status: 400,
},
};

export const mockEvmVerify = rest.post(`${AUTH_API_ROOT}/challenge/verify/evm`, (req, res, ctx) => {
const apiKey = req.headers.get('x-api-key');
const id = (req.body as Record<string, any>).message as string;

if (apiKey !== MOCK_API_KEY) {
return res(
ctx.status(401),
ctx.json({
message: 'Api Key Not Present',
}),
);
}

if (MockResponse[id]) {
return res(ctx.status(MockResponse[id].status), ctx.json(MockResponse[id].data));
}

throw new Error('mockEvmVerify: Not supported scenario');
});
Loading

0 comments on commit 4289372

Please sign in to comment.