opticedge-cloud-utils 1.0.31 → 1.0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/utils/tw-utils.d.ts +1 -0
- package/dist/utils/tw-utils.js +11 -0
- package/dist/utils/tw-utils.test.d.ts +1 -0
- package/dist/utils/tw-utils.test.js +26 -0
- package/dist/utils/tw-wallet.d.ts +1 -0
- package/dist/utils/tw-wallet.js +32 -0
- package/dist/utils/tw-wallet.test.d.ts +1 -0
- package/dist/utils/tw-wallet.test.js +94 -0
- package/package.json +3 -3
- package/src/index.ts +2 -1
- package/src/types/user.ts +2 -2
- package/src/utils/{thirdweb.test.ts → tw-utils.test.ts} +1 -1
- package/src/utils/tw-wallet.test.ts +89 -0
- package/src/utils/tw-wallet.ts +38 -0
- /package/src/utils/{thirdweb.ts → tw-utils.ts} +0 -0
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -27,4 +27,5 @@ __exportStar(require("./utils/env"), exports);
|
|
|
27
27
|
__exportStar(require("./utils/regex"), exports);
|
|
28
28
|
__exportStar(require("./utils/secrets"), exports);
|
|
29
29
|
__exportStar(require("./utils/task"), exports);
|
|
30
|
-
__exportStar(require("./utils/
|
|
30
|
+
__exportStar(require("./utils/tw-utils"), exports);
|
|
31
|
+
__exportStar(require("./utils/tw-wallet"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isValidWebhookSignature(secret: string, body: string, signature: string): boolean;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isValidWebhookSignature = isValidWebhookSignature;
|
|
7
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
8
|
+
function isValidWebhookSignature(secret, body, signature) {
|
|
9
|
+
const computedSignature = crypto_1.default.createHmac('sha256', secret).update(body).digest('hex');
|
|
10
|
+
return computedSignature === signature;
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const tw_utils_1 = require("./tw-utils");
|
|
7
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
8
|
+
describe('isValidWebhookSignature', () => {
|
|
9
|
+
const secret = 'test_secret';
|
|
10
|
+
const body = '{"message":"hello"}';
|
|
11
|
+
it('returns true for a valid signature', () => {
|
|
12
|
+
const validSignature = crypto_1.default.createHmac('sha256', secret).update(body).digest('hex');
|
|
13
|
+
expect((0, tw_utils_1.isValidWebhookSignature)(secret, body, validSignature)).toBe(true);
|
|
14
|
+
});
|
|
15
|
+
it('returns false for an invalid signature', () => {
|
|
16
|
+
const invalidSignature = 'invalidsignature123';
|
|
17
|
+
expect((0, tw_utils_1.isValidWebhookSignature)(secret, body, invalidSignature)).toBe(false);
|
|
18
|
+
});
|
|
19
|
+
it('returns false if body or secret is tampered', () => {
|
|
20
|
+
const originalSignature = crypto_1.default.createHmac('sha256', secret).update(body).digest('hex');
|
|
21
|
+
// wrong body
|
|
22
|
+
expect((0, tw_utils_1.isValidWebhookSignature)(secret, '{"message":"tampered"}', originalSignature)).toBe(false);
|
|
23
|
+
// wrong secret
|
|
24
|
+
expect((0, tw_utils_1.isValidWebhookSignature)('wrong_secret', body, originalSignature)).toBe(false);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function pregenerateInAppWallet(projectId: string, twClientId: string, twSecretKeyName: string, email: string): Promise<string | null>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.pregenerateInAppWallet = pregenerateInAppWallet;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const secrets_1 = require("./secrets");
|
|
9
|
+
async function pregenerateInAppWallet(projectId, twClientId, twSecretKeyName, email) {
|
|
10
|
+
const TW_SECRET_KEY = await (0, secrets_1.getSecret)(projectId, twSecretKeyName);
|
|
11
|
+
try {
|
|
12
|
+
const response = await axios_1.default.post('https://in-app-wallet.thirdweb.com/api/v1/pregenerate', { strategy: 'email', email }, {
|
|
13
|
+
headers: {
|
|
14
|
+
'x-secret-key': TW_SECRET_KEY,
|
|
15
|
+
'x-client-id': twClientId,
|
|
16
|
+
'Content-Type': 'application/json'
|
|
17
|
+
},
|
|
18
|
+
timeout: 5000
|
|
19
|
+
});
|
|
20
|
+
const wallet = response.data.wallet;
|
|
21
|
+
if (!wallet || !wallet.address) {
|
|
22
|
+
console.error('Invalid wallet response:', response.data);
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
console.log('Wallet pregeneration response:', wallet.address);
|
|
26
|
+
return wallet.address;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
console.error('Error pregenerating wallet:', error);
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const axios_1 = __importDefault(require("axios"));
|
|
40
|
+
const tw_wallet_1 = require("./tw-wallet");
|
|
41
|
+
const secrets = __importStar(require("./secrets"));
|
|
42
|
+
jest.mock('axios');
|
|
43
|
+
jest.mock('opticedge-cloud-utils');
|
|
44
|
+
jest.mock('./secrets');
|
|
45
|
+
const mockedAxios = axios_1.default;
|
|
46
|
+
const mockedGetSecret = secrets.getSecret;
|
|
47
|
+
describe('pregenerateInAppWallet', () => {
|
|
48
|
+
const mockProjectId = 'test-project';
|
|
49
|
+
const mockClientId = 'test-client-id';
|
|
50
|
+
const mockSecretKeyName = 'test-key';
|
|
51
|
+
const mockEmail = 'user@example.com';
|
|
52
|
+
const mockWalletAddress = '0xabc123';
|
|
53
|
+
const mockSecretValue = 'mock-secret-key';
|
|
54
|
+
beforeEach(() => {
|
|
55
|
+
jest.clearAllMocks();
|
|
56
|
+
});
|
|
57
|
+
it('returns wallet address on success', async () => {
|
|
58
|
+
mockedGetSecret.mockResolvedValue(mockSecretValue);
|
|
59
|
+
mockedAxios.post.mockResolvedValue({
|
|
60
|
+
data: {
|
|
61
|
+
wallet: {
|
|
62
|
+
address: mockWalletAddress
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
const result = await (0, tw_wallet_1.pregenerateInAppWallet)(mockProjectId, mockClientId, mockSecretKeyName, mockEmail);
|
|
67
|
+
expect(mockedGetSecret).toHaveBeenCalledWith(mockProjectId, mockSecretKeyName);
|
|
68
|
+
expect(mockedAxios.post).toHaveBeenCalledWith('https://in-app-wallet.thirdweb.com/api/v1/pregenerate', { strategy: 'email', email: mockEmail }, {
|
|
69
|
+
headers: {
|
|
70
|
+
'x-secret-key': mockSecretValue,
|
|
71
|
+
'x-client-id': mockClientId,
|
|
72
|
+
'Content-Type': 'application/json'
|
|
73
|
+
},
|
|
74
|
+
timeout: 5000
|
|
75
|
+
});
|
|
76
|
+
expect(result).toBe(mockWalletAddress);
|
|
77
|
+
});
|
|
78
|
+
it('returns null if wallet.address is missing', async () => {
|
|
79
|
+
mockedGetSecret.mockResolvedValue(mockSecretValue);
|
|
80
|
+
mockedAxios.post.mockResolvedValue({
|
|
81
|
+
data: {
|
|
82
|
+
wallet: {} // Missing address
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
const result = await (0, tw_wallet_1.pregenerateInAppWallet)(mockProjectId, mockClientId, mockSecretKeyName, mockEmail);
|
|
86
|
+
expect(result).toBeNull();
|
|
87
|
+
});
|
|
88
|
+
it('returns null on axios error', async () => {
|
|
89
|
+
mockedGetSecret.mockResolvedValue(mockSecretValue);
|
|
90
|
+
mockedAxios.post.mockRejectedValue(new Error('Network error'));
|
|
91
|
+
const result = await (0, tw_wallet_1.pregenerateInAppWallet)(mockProjectId, mockClientId, mockSecretKeyName, mockEmail);
|
|
92
|
+
expect(result).toBeNull();
|
|
93
|
+
});
|
|
94
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opticedge-cloud-utils",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.33",
|
|
4
4
|
"description": "Common utilities for cloud functions",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
"lint": "eslint . --ext .ts --fix",
|
|
11
11
|
"format": "prettier --write .",
|
|
12
12
|
"fix": "npm run lint && npm run format",
|
|
13
|
-
"prepare": "npm run build"
|
|
14
|
-
"publish": "npm version patch && npm publish"
|
|
13
|
+
"prepare": "npm run build"
|
|
15
14
|
},
|
|
16
15
|
"author": "Evans Musonda",
|
|
17
16
|
"license": "MIT",
|
|
18
17
|
"dependencies": {
|
|
19
18
|
"@google-cloud/secret-manager": "^6.0.1",
|
|
20
19
|
"@google-cloud/tasks": "^6.1.0",
|
|
20
|
+
"axios": "^1.10.0",
|
|
21
21
|
"google-auth-library": "^9.15.1",
|
|
22
22
|
"mongodb": "^6.16.0"
|
|
23
23
|
},
|
package/src/index.ts
CHANGED
package/src/types/user.ts
CHANGED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import axios from 'axios'
|
|
2
|
+
import { pregenerateInAppWallet } from './tw-wallet'
|
|
3
|
+
import * as secrets from './secrets'
|
|
4
|
+
|
|
5
|
+
jest.mock('axios')
|
|
6
|
+
jest.mock('opticedge-cloud-utils')
|
|
7
|
+
jest.mock('./secrets')
|
|
8
|
+
|
|
9
|
+
const mockedAxios = axios as jest.Mocked<typeof axios>
|
|
10
|
+
const mockedGetSecret = secrets.getSecret as jest.Mock
|
|
11
|
+
|
|
12
|
+
describe('pregenerateInAppWallet', () => {
|
|
13
|
+
const mockProjectId = 'test-project'
|
|
14
|
+
const mockClientId = 'test-client-id'
|
|
15
|
+
const mockSecretKeyName = 'test-key'
|
|
16
|
+
const mockEmail = 'user@example.com'
|
|
17
|
+
const mockWalletAddress = '0xabc123'
|
|
18
|
+
const mockSecretValue = 'mock-secret-key'
|
|
19
|
+
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
jest.clearAllMocks()
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('returns wallet address on success', async () => {
|
|
25
|
+
mockedGetSecret.mockResolvedValue(mockSecretValue)
|
|
26
|
+
mockedAxios.post.mockResolvedValue({
|
|
27
|
+
data: {
|
|
28
|
+
wallet: {
|
|
29
|
+
address: mockWalletAddress
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
const result = await pregenerateInAppWallet(
|
|
35
|
+
mockProjectId,
|
|
36
|
+
mockClientId,
|
|
37
|
+
mockSecretKeyName,
|
|
38
|
+
mockEmail
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
expect(mockedGetSecret).toHaveBeenCalledWith(mockProjectId, mockSecretKeyName)
|
|
42
|
+
expect(mockedAxios.post).toHaveBeenCalledWith(
|
|
43
|
+
'https://in-app-wallet.thirdweb.com/api/v1/pregenerate',
|
|
44
|
+
{ strategy: 'email', email: mockEmail },
|
|
45
|
+
{
|
|
46
|
+
headers: {
|
|
47
|
+
'x-secret-key': mockSecretValue,
|
|
48
|
+
'x-client-id': mockClientId,
|
|
49
|
+
'Content-Type': 'application/json'
|
|
50
|
+
},
|
|
51
|
+
timeout: 5000
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
expect(result).toBe(mockWalletAddress)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
it('returns null if wallet.address is missing', async () => {
|
|
59
|
+
mockedGetSecret.mockResolvedValue(mockSecretValue)
|
|
60
|
+
mockedAxios.post.mockResolvedValue({
|
|
61
|
+
data: {
|
|
62
|
+
wallet: {} // Missing address
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
const result = await pregenerateInAppWallet(
|
|
67
|
+
mockProjectId,
|
|
68
|
+
mockClientId,
|
|
69
|
+
mockSecretKeyName,
|
|
70
|
+
mockEmail
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
expect(result).toBeNull()
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it('returns null on axios error', async () => {
|
|
77
|
+
mockedGetSecret.mockResolvedValue(mockSecretValue)
|
|
78
|
+
mockedAxios.post.mockRejectedValue(new Error('Network error'))
|
|
79
|
+
|
|
80
|
+
const result = await pregenerateInAppWallet(
|
|
81
|
+
mockProjectId,
|
|
82
|
+
mockClientId,
|
|
83
|
+
mockSecretKeyName,
|
|
84
|
+
mockEmail
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
expect(result).toBeNull()
|
|
88
|
+
})
|
|
89
|
+
})
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import axios from 'axios'
|
|
2
|
+
import { getSecret } from './secrets'
|
|
3
|
+
|
|
4
|
+
export async function pregenerateInAppWallet(
|
|
5
|
+
projectId: string,
|
|
6
|
+
twClientId: string,
|
|
7
|
+
twSecretKeyName: string,
|
|
8
|
+
email: string
|
|
9
|
+
): Promise<string | null> {
|
|
10
|
+
const TW_SECRET_KEY = await getSecret(projectId, twSecretKeyName)
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
const response = await axios.post(
|
|
14
|
+
'https://in-app-wallet.thirdweb.com/api/v1/pregenerate',
|
|
15
|
+
{ strategy: 'email', email },
|
|
16
|
+
{
|
|
17
|
+
headers: {
|
|
18
|
+
'x-secret-key': TW_SECRET_KEY,
|
|
19
|
+
'x-client-id': twClientId,
|
|
20
|
+
'Content-Type': 'application/json'
|
|
21
|
+
},
|
|
22
|
+
timeout: 5000
|
|
23
|
+
}
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
const wallet = response.data.wallet
|
|
27
|
+
if (!wallet || !wallet.address) {
|
|
28
|
+
console.error('Invalid wallet response:', response.data)
|
|
29
|
+
return null
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
console.log('Wallet pregeneration response:', wallet.address)
|
|
33
|
+
return wallet.address
|
|
34
|
+
} catch (error) {
|
|
35
|
+
console.error('Error pregenerating wallet:', error)
|
|
36
|
+
return null
|
|
37
|
+
}
|
|
38
|
+
}
|
|
File without changes
|