@novastera-oss/nitro-metamask 0.7.7 → 0.7.9
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/android/src/main/cpp/cpp-adapter.cpp +1 -3
- package/android/src/main/java/com/margelo/nitro/nitrometamask/NitroMetamaskPackage.kt +3 -2
- package/app.plugin.js +46 -89
- package/lib/typescript/src/__tests__/appPlugin.test.d.ts +2 -0
- package/lib/typescript/src/__tests__/appPlugin.test.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/__tests__/appPlugin.test.ts +79 -0
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
#include <fbjni/fbjni.h>
|
|
2
1
|
#include <jni.h>
|
|
3
|
-
|
|
4
2
|
#include "NitroMetamaskOnLoad.hpp"
|
|
5
3
|
|
|
6
4
|
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
|
|
7
|
-
return
|
|
5
|
+
return margelo::nitro::nitrometamask::initialize(vm);
|
|
8
6
|
}
|
|
@@ -37,9 +37,10 @@ class NitroMetamaskPackage : BaseReactPackage() {
|
|
|
37
37
|
"NitroMetamaskPackage",
|
|
38
38
|
false, // canOverrideExistingModule
|
|
39
39
|
true, // needsEagerInit
|
|
40
|
+
true, // hasConstants
|
|
40
41
|
false, // isCxxModule
|
|
41
|
-
true
|
|
42
|
-
)
|
|
42
|
+
true // isTurboModule
|
|
43
|
+
)
|
|
43
44
|
)
|
|
44
45
|
}
|
|
45
46
|
}
|
package/app.plugin.js
CHANGED
|
@@ -6,109 +6,66 @@ const withMetamaskAppDelegate = (config) => {
|
|
|
6
6
|
|
|
7
7
|
// Check if AppDelegate is Swift
|
|
8
8
|
if (modResults.language === 'swift') {
|
|
9
|
-
//
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
// Swift AppDelegate should not import Nitro/MetaMask modules directly.
|
|
10
|
+
// Cleanup legacy injected imports from previous plugin versions.
|
|
11
|
+
modResults.contents = modResults.contents.replace(
|
|
12
|
+
/^\s*import\s+metamask_ios_sdk\s*\n?/gm,
|
|
13
|
+
''
|
|
14
|
+
);
|
|
15
|
+
modResults.contents = modResults.contents.replace(
|
|
16
|
+
/^\s*import\s+NitroMetamask\s*\n?/gm,
|
|
17
|
+
''
|
|
18
|
+
);
|
|
16
19
|
|
|
17
|
-
//
|
|
18
|
-
if
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const lastImport = imports[imports.length - 1];
|
|
24
|
-
const lastImportIndex = modResults.contents.lastIndexOf(lastImport);
|
|
25
|
-
modResults.contents =
|
|
26
|
-
modResults.contents.slice(0, lastImportIndex + lastImport.length) +
|
|
27
|
-
'\nimport NitroMetamask' +
|
|
28
|
-
modResults.contents.slice(lastImportIndex + lastImport.length);
|
|
29
|
-
} else {
|
|
30
|
-
// No imports found, add at the top after the first line
|
|
31
|
-
const firstLineIndex = modResults.contents.indexOf('\n');
|
|
32
|
-
modResults.contents =
|
|
33
|
-
modResults.contents.slice(0, firstLineIndex + 1) +
|
|
34
|
-
'import NitroMetamask\n' +
|
|
35
|
-
modResults.contents.slice(firstLineIndex + 1);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
20
|
+
// Optional migration cleanup: remove legacy injected MetaMask handler
|
|
21
|
+
// block if it exists in Swift AppDelegate files.
|
|
22
|
+
modResults.contents = modResults.contents.replace(
|
|
23
|
+
/\n\s*\/\/ Handle deep links from MetaMask wallet[\s\S]*?MetaMaskSDK\.sharedInstance\?\.handleUrl\(url\)[\s\S]*?return false\s*\n\s*\}/g,
|
|
24
|
+
''
|
|
25
|
+
);
|
|
38
26
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
open url: URL,
|
|
52
|
-
options: [UIApplication.OpenURLOptionsKey: Any] = [:]
|
|
53
|
-
) -> Bool {
|
|
54
|
-
// Check if this is a MetaMask deep link (host="mmsdk")
|
|
55
|
-
if let components = URLComponents(url: url, resolvingAgainstBaseURL: true),
|
|
56
|
-
components.host == "mmsdk" {
|
|
57
|
-
// Handle MetaMask deep link return
|
|
58
|
-
MetaMaskSDK.sharedInstance?.handleUrl(url)
|
|
59
|
-
return true
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Handle other deep links (e.g., React Native Linking)
|
|
63
|
-
return false
|
|
64
|
-
}`;
|
|
65
|
-
|
|
66
|
-
// Insert before the last closing brace of the AppDelegate class
|
|
67
|
-
// Try to find the closing brace of the class before @end or end of file
|
|
68
|
-
const classEndPattern = /(\s+)\}(?=\s*(?:@end|$))/;
|
|
69
|
-
const match = modResults.contents.match(classEndPattern);
|
|
70
|
-
if (match) {
|
|
71
|
-
const indent = match[1];
|
|
72
|
-
const insertIndex = match.index;
|
|
73
|
-
modResults.contents =
|
|
74
|
-
modResults.contents.slice(0, insertIndex) +
|
|
75
|
-
deepLinkHandler.replace(/^ /gm, indent) +
|
|
76
|
-
'\n' + indent + '}' +
|
|
77
|
-
modResults.contents.slice(insertIndex + match[0].length);
|
|
78
|
-
} else {
|
|
79
|
-
// Fallback: append before @end
|
|
27
|
+
return config;
|
|
28
|
+
} else if (modResults.language === 'objc') {
|
|
29
|
+
// Handle Objective-C AppDelegate
|
|
30
|
+
// Remove stale direct SDK import if present. Importing MetaMaskSDK headers
|
|
31
|
+
// in Objective-C (.m) can pull C++ headers and fail non-ObjC++ builds.
|
|
32
|
+
modResults.contents = modResults.contents.replace(
|
|
33
|
+
/^\s*#import\s+<MetaMaskSDK\/MetaMaskSDK\.h>\s*\n?/gm,
|
|
34
|
+
''
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
// Migrate legacy direct call to a runtime-safe invocation in Objective-C.
|
|
38
|
+
if (modResults.contents.includes('[[MetaMaskSDK sharedInstance] handleUrl:url];')) {
|
|
80
39
|
modResults.contents = modResults.contents.replace(
|
|
81
|
-
|
|
82
|
-
|
|
40
|
+
/\[\[MetaMaskSDK sharedInstance\] handleUrl:url\];/g,
|
|
41
|
+
`Class metaMaskSDKClass = NSClassFromString(@"MetaMaskSDK");
|
|
42
|
+
id sharedInstance = [metaMaskSDKClass respondsToSelector:@selector(sharedInstance)]
|
|
43
|
+
? [metaMaskSDKClass performSelector:@selector(sharedInstance)]
|
|
44
|
+
: nil;
|
|
45
|
+
if (sharedInstance && [sharedInstance respondsToSelector:@selector(handleUrl:)]) {
|
|
46
|
+
[sharedInstance performSelector:@selector(handleUrl:) withObject:url];
|
|
47
|
+
}`
|
|
83
48
|
);
|
|
84
49
|
}
|
|
85
|
-
|
|
86
|
-
//
|
|
87
|
-
if (modResults.contents.includes('
|
|
50
|
+
|
|
51
|
+
// Skip injection if handler already exists after migration.
|
|
52
|
+
if (modResults.contents.includes('[components.host isEqualToString:@"mmsdk"]')) {
|
|
88
53
|
return config;
|
|
89
54
|
}
|
|
90
55
|
|
|
91
|
-
// Add import
|
|
92
|
-
if (!modResults.contents.includes('#import <MetaMaskSDK/MetaMaskSDK.h>')) {
|
|
93
|
-
const importRegex = /^#import\s+.*$/gm;
|
|
94
|
-
const imports = modResults.contents.match(importRegex);
|
|
95
|
-
if (imports && imports.length > 0) {
|
|
96
|
-
const lastImport = imports[imports.length - 1];
|
|
97
|
-
const lastImportIndex = modResults.contents.lastIndexOf(lastImport);
|
|
98
|
-
modResults.contents =
|
|
99
|
-
modResults.contents.slice(0, lastImportIndex + lastImport.length) +
|
|
100
|
-
'\n#import <MetaMaskSDK/MetaMaskSDK.h>' +
|
|
101
|
-
modResults.contents.slice(lastImportIndex + lastImport.length);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
56
|
const objcHandler = `
|
|
106
57
|
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
|
|
107
58
|
// Check if this is a MetaMask deep link (host="mmsdk")
|
|
108
59
|
NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:YES];
|
|
109
60
|
if ([components.host isEqualToString:@"mmsdk"]) {
|
|
110
61
|
// Handle MetaMask deep link return
|
|
111
|
-
|
|
62
|
+
Class metaMaskSDKClass = NSClassFromString(@"MetaMaskSDK");
|
|
63
|
+
id sharedInstance = [metaMaskSDKClass respondsToSelector:@selector(sharedInstance)]
|
|
64
|
+
? [metaMaskSDKClass performSelector:@selector(sharedInstance)]
|
|
65
|
+
: nil;
|
|
66
|
+
if (sharedInstance && [sharedInstance respondsToSelector:@selector(handleUrl:)]) {
|
|
67
|
+
[sharedInstance performSelector:@selector(handleUrl:) withObject:url];
|
|
68
|
+
}
|
|
112
69
|
return YES;
|
|
113
70
|
}
|
|
114
71
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"appPlugin.test.d.ts","sourceRoot":"","sources":["../../../../src/__tests__/appPlugin.test.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,uBAAuB,KAAiC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@novastera-oss/nitro-metamask",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.9",
|
|
4
4
|
"description": "Native mobile MetaMask wallet integration for React Native. Part of Novastera CRM/ERP platform ecosystem. Provides secure authentication and message signing for Web3 mobile applications.",
|
|
5
5
|
"main": "./lib/commonjs/index.js",
|
|
6
6
|
"module": "./lib/module/index.js",
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
jest.mock('@expo/config-plugins', () => ({
|
|
2
|
+
withAppDelegate: (config: any, action: (cfg: any) => any) => action(config),
|
|
3
|
+
}))
|
|
4
|
+
|
|
5
|
+
const withMetamaskAppDelegate = require('../../app.plugin.js')
|
|
6
|
+
|
|
7
|
+
describe('app.plugin.js', () => {
|
|
8
|
+
it('removes stale Swift imports and does not inject handler', () => {
|
|
9
|
+
const config = {
|
|
10
|
+
modResults: {
|
|
11
|
+
language: 'swift',
|
|
12
|
+
contents: `import UIKit
|
|
13
|
+
import metamask_ios_sdk
|
|
14
|
+
import NitroMetamask
|
|
15
|
+
|
|
16
|
+
class AppDelegate: NSObject {
|
|
17
|
+
}
|
|
18
|
+
`,
|
|
19
|
+
},
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const result = withMetamaskAppDelegate(config)
|
|
23
|
+
const contents: string = result.modResults.contents
|
|
24
|
+
|
|
25
|
+
expect(contents).not.toContain('import metamask_ios_sdk')
|
|
26
|
+
expect(contents).not.toContain('import NitroMetamask')
|
|
27
|
+
expect(contents).not.toContain('MetaMaskSDK.sharedInstance?.handleUrl(url)')
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('keeps Swift AppDelegate untouched apart from cleanup', () => {
|
|
31
|
+
const config = {
|
|
32
|
+
modResults: {
|
|
33
|
+
language: 'swift',
|
|
34
|
+
contents: `import UIKit
|
|
35
|
+
|
|
36
|
+
class AppDelegate: NSObject {
|
|
37
|
+
}
|
|
38
|
+
`,
|
|
39
|
+
},
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const result = withMetamaskAppDelegate(config)
|
|
43
|
+
const contents: string = result.modResults.contents
|
|
44
|
+
|
|
45
|
+
expect(contents).toContain('import UIKit')
|
|
46
|
+
expect(contents).not.toContain('import NitroMetamask')
|
|
47
|
+
expect(contents).not.toContain('MetaMaskSDK.sharedInstance?.handleUrl(url)')
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('migrates Objective-C direct SDK usage to runtime-safe calls', () => {
|
|
51
|
+
const config = {
|
|
52
|
+
modResults: {
|
|
53
|
+
language: 'objc',
|
|
54
|
+
contents: `#import "AppDelegate.h"
|
|
55
|
+
#import <MetaMaskSDK/MetaMaskSDK.h>
|
|
56
|
+
|
|
57
|
+
@implementation AppDelegate
|
|
58
|
+
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
|
|
59
|
+
NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:YES];
|
|
60
|
+
if ([components.host isEqualToString:@"mmsdk"]) {
|
|
61
|
+
[[MetaMaskSDK sharedInstance] handleUrl:url];
|
|
62
|
+
return YES;
|
|
63
|
+
}
|
|
64
|
+
return NO;
|
|
65
|
+
}
|
|
66
|
+
@end
|
|
67
|
+
`,
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const result = withMetamaskAppDelegate(config)
|
|
72
|
+
const contents: string = result.modResults.contents
|
|
73
|
+
|
|
74
|
+
expect(contents).not.toContain('#import <MetaMaskSDK/MetaMaskSDK.h>')
|
|
75
|
+
expect(contents).toContain('NSClassFromString(@"MetaMaskSDK")')
|
|
76
|
+
expect(contents).toContain('[sharedInstance performSelector:@selector(handleUrl:) withObject:url]')
|
|
77
|
+
expect(contents).not.toContain('[[MetaMaskSDK sharedInstance] handleUrl:url];')
|
|
78
|
+
})
|
|
79
|
+
})
|