Skip to content

Commit 979dafa

Browse files
justinnoutJustin Herrera
and
Justin Herrera
authored
Support new multi-chain wallet functionality (#92)
* Support new multi-chain wallet functionality * Fix formatting * Update unit tests to conform to best practices Co-authored-by: Justin Herrera <[email protected]>
1 parent e4cf56b commit 979dafa

27 files changed

+220
-76
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
npm-debug.log*
1111
yarn-error.log*
1212
.DS_Store
13+
.vscode
1314

1415
# Use Yarn!
1516
package-lock.json
@@ -19,4 +20,4 @@ package-lock.json
1920
/.nyc_output
2021

2122
# ENV
22-
.env
23+
.env

src/modules/users/index.ts

+32-12
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import { BaseModule } from '../base-module';
22
import { createApiKeyMissingError } from '../../core/sdk-exceptions';
33
import { post, get } from '../../utils/rest';
44
import { generateIssuerFromPublicAddress } from '../../utils/issuer';
5-
import { MagicUserMetadata } from '../../types';
5+
import { MagicUserMetadata, MagicWallet } from '../../types';
6+
import { WalletType } from '../../types/wallet-types';
67

78
export class UsersModule extends BaseModule {
89
// --- User logout endpoints
@@ -26,6 +27,33 @@ export class UsersModule extends BaseModule {
2627
// --- User metadata endpoints
2728

2829
public async getMetadataByIssuer(issuer: string): Promise<MagicUserMetadata> {
30+
return this.getMetadataByIssuerAndWallet(issuer, WalletType.NONE);
31+
}
32+
33+
public async getMetadataByToken(DIDToken: string): Promise<MagicUserMetadata> {
34+
const issuer = this.sdk.token.getIssuer(DIDToken);
35+
return this.getMetadataByIssuer(issuer);
36+
}
37+
38+
public async getMetadataByPublicAddress(publicAddress: string): Promise<MagicUserMetadata> {
39+
const issuer = generateIssuerFromPublicAddress(publicAddress);
40+
return this.getMetadataByIssuer(issuer);
41+
}
42+
43+
public async getMetadataByTokenAndWallet(DIDToken: string, walletType: WalletType): Promise<MagicUserMetadata> {
44+
const issuer = this.sdk.token.getIssuer(DIDToken);
45+
return this.getMetadataByIssuerAndWallet(issuer, walletType);
46+
}
47+
48+
public async getMetadataByPublicAddressAndWallet(
49+
publicAddress: string,
50+
walletType: WalletType,
51+
): Promise<MagicUserMetadata> {
52+
const issuer = generateIssuerFromPublicAddress(publicAddress);
53+
return this.getMetadataByIssuerAndWallet(issuer, walletType);
54+
}
55+
56+
public async getMetadataByIssuerAndWallet(issuer: string, walletType: WalletType): Promise<MagicUserMetadata> {
2957
if (!this.sdk.secretApiKey) throw createApiKeyMissingError();
3058

3159
const data = await get<{
@@ -34,24 +62,16 @@ export class UsersModule extends BaseModule {
3462
email: string | null;
3563
oauth_provider: string | null;
3664
phone_number: string | null;
37-
}>(`${this.sdk.apiBaseUrl}/v1/admin/auth/user/get`, this.sdk.secretApiKey, { issuer });
65+
wallets: MagicWallet[] | null;
66+
}>(`${this.sdk.apiBaseUrl}/v1/admin/auth/user/get?wallet_type=${walletType}`, this.sdk.secretApiKey, { issuer });
3867

3968
return {
4069
issuer: data.issuer ?? null,
4170
publicAddress: data.public_address ?? null,
4271
email: data.email ?? null,
4372
oauthProvider: data.oauth_provider ?? null,
4473
phoneNumber: data.phone_number ?? null,
74+
wallets: data.wallets ?? null,
4575
};
4676
}
47-
48-
public async getMetadataByToken(DIDToken: string): Promise<MagicUserMetadata> {
49-
const issuer = this.sdk.token.getIssuer(DIDToken);
50-
return this.getMetadataByIssuer(issuer);
51-
}
52-
53-
public async getMetadataByPublicAddress(publicAddress: string): Promise<MagicUserMetadata> {
54-
const issuer = generateIssuerFromPublicAddress(publicAddress);
55-
return this.getMetadataByIssuer(issuer);
56-
}
5777
}

src/types/sdk-types.ts

+7
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,17 @@ export interface MagicAdminSDKAdditionalConfiguration {
22
endpoint?: string;
33
}
44

5+
export interface MagicWallet {
6+
network: string | null;
7+
publicAddress: string | null;
8+
walletType: string | null;
9+
}
10+
511
export interface MagicUserMetadata {
612
issuer: string | null;
713
publicAddress: string | null;
814
email: string | null;
915
oauthProvider: string | null;
1016
phoneNumber: string | null;
17+
wallets: MagicWallet[] | null;
1118
}

src/types/wallet-types.ts

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
export enum WalletType {
2+
ETH = 'ETH',
3+
HARMONY = 'HARMONY',
4+
ICON = 'ICON',
5+
FLOW = 'FLOW',
6+
TEZOS = 'TEZOS',
7+
ZILLIQA = 'ZILLIQA',
8+
POLKADOT = 'POLKADOT',
9+
SOLANA = 'SOLANA',
10+
AVAX = 'AVAX',
11+
ALGOD = 'ALGOD',
12+
COSMOS = 'COSMOS',
13+
CELO = 'CELO',
14+
BITCOIN = 'BITCOIN',
15+
NEAR = 'NEAR',
16+
HELIUM = 'HELIUM',
17+
CONFLUX = 'CONFLUX',
18+
TERRA = 'TERRA',
19+
TAQUITO = 'TAQUITO',
20+
ED = 'ED',
21+
HEDERA = 'HEDERA',
22+
NONE = 'NONE',
23+
ANY = 'ANY',
24+
}

test/spec/core/sdk-exceptions/error-factories.spec.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ function errorAssertions(
2222
expect(error.data).toEqual(expectedData);
2323
}
2424

25-
test('#01: Creates `ERROR_DIDT_EXPIRED` error', async () => {
25+
test('Creates `ERROR_DIDT_EXPIRED` error', async () => {
2626
const error = createTokenExpiredError();
2727
errorAssertions(error, 'ERROR_DIDT_EXPIRED', 'DID Token has expired. Request failed authentication.');
2828
});
2929

30-
test('#02: Creates `ERROR_DIDT_CANNOT_BE_USED_YET` error', async () => {
30+
test('Creates `ERROR_DIDT_CANNOT_BE_USED_YET` error', async () => {
3131
const error = createTokenCannotBeUsedYetError();
3232
errorAssertions(
3333
error,
@@ -36,7 +36,7 @@ test('#02: Creates `ERROR_DIDT_CANNOT_BE_USED_YET` error', async () => {
3636
);
3737
});
3838

39-
test('#03: Creates `ERROR_INCORRECT_SIGNER_ADDR` error', async () => {
39+
test('Creates `ERROR_INCORRECT_SIGNER_ADDR` error', async () => {
4040
const error = createIncorrectSignerAddressError();
4141
errorAssertions(
4242
error,
@@ -45,12 +45,12 @@ test('#03: Creates `ERROR_INCORRECT_SIGNER_ADDR` error', async () => {
4545
);
4646
});
4747

48-
test('#04: Creates `ERROR_FAILED_RECOVERING_PROOF` error', async () => {
48+
test('Creates `ERROR_FAILED_RECOVERING_PROOF` error', async () => {
4949
const error = createFailedRecoveringProofError();
5050
errorAssertions(error, 'ERROR_FAILED_RECOVERING_PROOF', 'Failed to recover proof. Request failed authentication.');
5151
});
5252

53-
test('#05: Creates `ERROR_SECRET_API_KEY_MISSING` error', async () => {
53+
test('Creates `ERROR_SECRET_API_KEY_MISSING` error', async () => {
5454
const error = createApiKeyMissingError();
5555
errorAssertions(
5656
error,
@@ -59,7 +59,7 @@ test('#05: Creates `ERROR_SECRET_API_KEY_MISSING` error', async () => {
5959
);
6060
});
6161

62-
test('#06: Creates `SERVICE_ERROR` error with empty `data` property', async () => {
62+
test('Creates `SERVICE_ERROR` error with empty `data` property', async () => {
6363
const error = createServiceError();
6464
errorAssertions(
6565
error,
@@ -68,7 +68,7 @@ test('#06: Creates `SERVICE_ERROR` error with empty `data` property', async () =
6868
);
6969
});
7070

71-
test('#07: Creates `SERVICE_ERROR` error with non-empty `data` property', async () => {
71+
test('Creates `SERVICE_ERROR` error with non-empty `data` property', async () => {
7272
const error = createServiceError('hello', 'world');
7373
errorAssertions(
7474
error,
@@ -78,7 +78,7 @@ test('#07: Creates `SERVICE_ERROR` error with non-empty `data` property', async
7878
);
7979
});
8080

81-
test('#08: Creates `EXPECTED_BEARER_STRING` error', async () => {
81+
test('Creates `EXPECTED_BEARER_STRING` error', async () => {
8282
const error = createExpectedBearerStringError();
8383
errorAssertions(error, 'EXPECTED_BEARER_STRING', 'Expected argument to be a string in the `Bearer {token}` format.');
8484
});

test/spec/core/sdk-exceptions/magic-admin-sdk-error/constructor.spec.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { MagicAdminSDKError } from '../../../../../src/core/sdk-exceptions';
22

3-
test('#01: Instantiates `MagicAdminSDKError` with empty `data` property', () => {
3+
test('Instantiates `MagicAdminSDKError` with empty `data` property', () => {
44
const error = new MagicAdminSDKError('TEST_CODE' as any, 'test message');
55
expect(error instanceof MagicAdminSDKError).toBe(true);
66
expect(error.message).toBe('Magic Admin SDK Error: [TEST_CODE] test message');
77
expect(error.code).toBe('TEST_CODE');
88
expect(error.data).toEqual([]);
99
});
1010

11-
test('#01: Instantiates `MagicAdminSDKError` with non-empty `data` property', () => {
11+
test('Instantiates `MagicAdminSDKError` with non-empty `data` property', () => {
1212
const error = new MagicAdminSDKError('TEST_CODE' as any, 'test message', ['hello world']);
1313
expect(error instanceof MagicAdminSDKError).toBe(true);
1414
expect(error.message).toBe('Magic Admin SDK Error: [TEST_CODE] test message');

test/spec/core/sdk/constructor.spec.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { TokenModule } from '../../../../src/modules/token';
55
import { UsersModule } from '../../../../src/modules/users';
66
import { UtilsModule } from '../../../../src/modules/utils';
77

8-
test('#01: Initialize `MagicAdminSDK`', () => {
8+
test('Initialize `MagicAdminSDK`', () => {
99
const magic = new Magic(API_KEY);
1010

1111
expect(magic.secretApiKey).toBe(API_KEY);
@@ -14,7 +14,7 @@ test('#01: Initialize `MagicAdminSDK`', () => {
1414
expect(magic.users instanceof UsersModule).toBe(true);
1515
});
1616

17-
test('#02: Initialize `MagicAdminSDK` with custom endpoint', () => {
17+
test('Initialize `MagicAdminSDK` with custom endpoint', () => {
1818
const magic = new Magic(API_KEY, { endpoint: 'https://example.com' });
1919

2020
expect(magic.secretApiKey).toBe(API_KEY);
@@ -24,7 +24,7 @@ test('#02: Initialize `MagicAdminSDK` with custom endpoint', () => {
2424
expect(magic.utils instanceof UtilsModule).toBe(true);
2525
});
2626

27-
test('#03: Strips trailing slash(es) from custom endpoint argument', () => {
27+
test('Strips trailing slash(es) from custom endpoint argument', () => {
2828
const magicA = new Magic(API_KEY, { endpoint: 'https://example.com/' });
2929
const magicB = new Magic(API_KEY, { endpoint: 'https://example.com//' });
3030
const magicC = new Magic(API_KEY, { endpoint: 'https://example.com///' });

test/spec/modules/base-module/constructor.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { MagicAdminSDK } from '../../../../src/core/sdk';
22
import { BaseModule } from '../../../../src/modules/base-module';
33
import { createMagicAdminSDK } from '../../../lib/factories';
44

5-
test('#01: Initializes `BaseModule`', () => {
5+
test('Initializes `BaseModule`', () => {
66
const sdk = createMagicAdminSDK();
77

88
const baseModule: any = new (BaseModule as any)(sdk);

test/spec/modules/token/decode.spec.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ import { createMagicAdminSDK } from '../../../lib/factories';
22
import { VALID_DIDT, VALID_DIDT_DECODED, INVALID_DIDT_MALFORMED_CLAIM } from '../../../lib/constants';
33
import { createMalformedTokenError } from '../../../../src/core/sdk-exceptions';
44

5-
test('#01: Successfully decodes DIDT', async () => {
5+
test('Successfully decodes DIDT', async () => {
66
const sdk = createMagicAdminSDK();
77
const result = sdk.token.decode(VALID_DIDT);
88
expect(result).toEqual(VALID_DIDT_DECODED);
99
});
1010

11-
test('#02: Throws error if token is malformed', async () => {
11+
test('Throws error if token is malformed', async () => {
1212
const sdk = createMagicAdminSDK();
1313
const expectedError = createMalformedTokenError();
1414
expect(() => sdk.token.decode(INVALID_DIDT_MALFORMED_CLAIM)).toThrow(expectedError);

test/spec/modules/token/getIssuer.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { createMagicAdminSDK } from '../../../lib/factories';
22
import { VALID_DIDT, VALID_DIDT_PARSED_CLAIMS } from '../../../lib/constants';
33

4-
test('#01: Successfully gets issuer from DIDT', () => {
4+
test('Successfully gets issuer from DIDT', () => {
55
const sdk = createMagicAdminSDK();
66
const result = sdk.token.getIssuer(VALID_DIDT);
77
const expected = VALID_DIDT_PARSED_CLAIMS.iss;

test/spec/modules/token/getPublicAddress.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { createMagicAdminSDK } from '../../../lib/factories';
22
import { VALID_DIDT, VALID_DIDT_PARSED_CLAIMS } from '../../../lib/constants';
33

4-
test('#01: Successfully gets public address from DIDT', () => {
4+
test('Successfully gets public address from DIDT', () => {
55
const sdk = createMagicAdminSDK();
66
const result = sdk.token.getPublicAddress(VALID_DIDT);
77
const expected = VALID_DIDT_PARSED_CLAIMS.iss.split(':')[2];

test/spec/modules/token/validate.spec.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -15,36 +15,36 @@ import {
1515
createTokenCannotBeUsedYetError,
1616
} from '../../../../src/core/sdk-exceptions';
1717

18-
test('#01: Successfully validates DIDT', async () => {
18+
test('Successfully validates DIDT', async () => {
1919
const sdk = createMagicAdminSDK();
2020
expect(() => sdk.token.validate(VALID_DIDT)).not.toThrow();
2121
});
2222

23-
test('#02: Fails when signer address mismatches signature', async () => {
23+
test('Fails when signer address mismatches signature', async () => {
2424
const sdk = createMagicAdminSDK();
2525
const expectedError = createIncorrectSignerAddressError();
2626
expect(() => sdk.token.validate(INVALID_SIGNER_DIDT)).toThrow(expectedError);
2727
});
2828

29-
test('#03: Fails when given expired token', async () => {
29+
test('Fails when given expired token', async () => {
3030
const sdk = createMagicAdminSDK();
3131
const expectedError = createTokenExpiredError();
3232
expect(() => sdk.token.validate(EXPIRED_DIDT)).toThrow(expectedError);
3333
});
3434

35-
test('#04: Fails when given a token with a future `nbf` timestamp', async () => {
35+
test('Fails when given a token with a future `nbf` timestamp', async () => {
3636
const sdk = createMagicAdminSDK();
3737
const expectedError = createTokenCannotBeUsedYetError();
3838
expect(() => sdk.token.validate(VALID_FUTURE_MARKED_DIDT)).toThrow(expectedError);
3939
});
4040

41-
test('#05: Fails if signature recovery rejects', async () => {
41+
test('Fails if signature recovery rejects', async () => {
4242
const sdk = createMagicAdminSDK();
4343
const expectedError = createFailedRecoveringProofError();
4444
expect(() => sdk.token.validate(VALID_DIDT_WITH_INVALID_RECOVERY_BIT)).toThrow(expectedError);
4545
});
4646

47-
test('#06: Fails if decoding token fails', async () => {
47+
test('Fails if decoding token fails', async () => {
4848
const sdk = createMagicAdminSDK();
4949
const expectedError = createMalformedTokenError();
5050
expect(() => sdk.token.validate(INVALID_DIDT_MALFORMED_CLAIM)).toThrow(expectedError);

0 commit comments

Comments
 (0)