@novastera-oss/nitro-metamask 0.7.5 → 0.7.8
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 -24
- 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 +85 -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,13 +6,16 @@ const withMetamaskAppDelegate = (config) => {
|
|
|
6
6
|
|
|
7
7
|
// Check if AppDelegate is Swift
|
|
8
8
|
if (modResults.language === 'swift') {
|
|
9
|
-
//
|
|
10
|
-
if (modResults.contents.includes('
|
|
11
|
-
|
|
9
|
+
// Migrate stale/incorrect import if present
|
|
10
|
+
if (modResults.contents.includes('import metamask_ios_sdk')) {
|
|
11
|
+
modResults.contents = modResults.contents.replace(
|
|
12
|
+
/import\s+metamask_ios_sdk/g,
|
|
13
|
+
'import NitroMetamask'
|
|
14
|
+
);
|
|
12
15
|
}
|
|
13
|
-
|
|
14
|
-
// Add import if not present
|
|
15
|
-
if (!modResults.contents.includes('import
|
|
16
|
+
|
|
17
|
+
// Add NitroMetamask import if not present
|
|
18
|
+
if (!modResults.contents.includes('import NitroMetamask')) {
|
|
16
19
|
// Find the last import statement and add after it
|
|
17
20
|
const importRegex = /^import\s+.*$/gm;
|
|
18
21
|
const imports = modResults.contents.match(importRegex);
|
|
@@ -21,17 +24,22 @@ const withMetamaskAppDelegate = (config) => {
|
|
|
21
24
|
const lastImportIndex = modResults.contents.lastIndexOf(lastImport);
|
|
22
25
|
modResults.contents =
|
|
23
26
|
modResults.contents.slice(0, lastImportIndex + lastImport.length) +
|
|
24
|
-
'\nimport
|
|
27
|
+
'\nimport NitroMetamask' +
|
|
25
28
|
modResults.contents.slice(lastImportIndex + lastImport.length);
|
|
26
29
|
} else {
|
|
27
30
|
// No imports found, add at the top after the first line
|
|
28
31
|
const firstLineIndex = modResults.contents.indexOf('\n');
|
|
29
32
|
modResults.contents =
|
|
30
33
|
modResults.contents.slice(0, firstLineIndex + 1) +
|
|
31
|
-
'import
|
|
34
|
+
'import NitroMetamask\n' +
|
|
32
35
|
modResults.contents.slice(firstLineIndex + 1);
|
|
33
36
|
}
|
|
34
37
|
}
|
|
38
|
+
|
|
39
|
+
// Check if the method already exists
|
|
40
|
+
if (modResults.contents.includes('MetaMaskSDK.sharedInstance?.handleUrl')) {
|
|
41
|
+
return config;
|
|
42
|
+
}
|
|
35
43
|
|
|
36
44
|
// Add the deep link handler method
|
|
37
45
|
const deepLinkHandler = `
|
|
@@ -76,22 +84,30 @@ const withMetamaskAppDelegate = (config) => {
|
|
|
76
84
|
}
|
|
77
85
|
} else if (modResults.language === 'objc') {
|
|
78
86
|
// Handle Objective-C AppDelegate
|
|
79
|
-
if
|
|
80
|
-
|
|
87
|
+
// Remove stale direct SDK import if present. Importing MetaMaskSDK headers
|
|
88
|
+
// in Objective-C (.m) can pull C++ headers and fail non-ObjC++ builds.
|
|
89
|
+
modResults.contents = modResults.contents.replace(
|
|
90
|
+
/^\s*#import\s+<MetaMaskSDK\/MetaMaskSDK\.h>\s*\n?/gm,
|
|
91
|
+
''
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
// Migrate legacy direct call to a runtime-safe invocation in Objective-C.
|
|
95
|
+
if (modResults.contents.includes('[[MetaMaskSDK sharedInstance] handleUrl:url];')) {
|
|
96
|
+
modResults.contents = modResults.contents.replace(
|
|
97
|
+
/\[\[MetaMaskSDK sharedInstance\] handleUrl:url\];/g,
|
|
98
|
+
`Class metaMaskSDKClass = NSClassFromString(@"MetaMaskSDK");
|
|
99
|
+
id sharedInstance = [metaMaskSDKClass respondsToSelector:@selector(sharedInstance)]
|
|
100
|
+
? [metaMaskSDKClass performSelector:@selector(sharedInstance)]
|
|
101
|
+
: nil;
|
|
102
|
+
if (sharedInstance && [sharedInstance respondsToSelector:@selector(handleUrl:)]) {
|
|
103
|
+
[sharedInstance performSelector:@selector(handleUrl:) withObject:url];
|
|
104
|
+
}`
|
|
105
|
+
);
|
|
81
106
|
}
|
|
82
|
-
|
|
83
|
-
//
|
|
84
|
-
if (
|
|
85
|
-
|
|
86
|
-
const imports = modResults.contents.match(importRegex);
|
|
87
|
-
if (imports && imports.length > 0) {
|
|
88
|
-
const lastImport = imports[imports.length - 1];
|
|
89
|
-
const lastImportIndex = modResults.contents.lastIndexOf(lastImport);
|
|
90
|
-
modResults.contents =
|
|
91
|
-
modResults.contents.slice(0, lastImportIndex + lastImport.length) +
|
|
92
|
-
'\n#import <MetaMaskSDK/MetaMaskSDK.h>' +
|
|
93
|
-
modResults.contents.slice(lastImportIndex + lastImport.length);
|
|
94
|
-
}
|
|
107
|
+
|
|
108
|
+
// Skip injection if handler already exists after migration.
|
|
109
|
+
if (modResults.contents.includes('[components.host isEqualToString:@"mmsdk"]')) {
|
|
110
|
+
return config;
|
|
95
111
|
}
|
|
96
112
|
|
|
97
113
|
const objcHandler = `
|
|
@@ -100,7 +116,13 @@ const withMetamaskAppDelegate = (config) => {
|
|
|
100
116
|
NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:YES];
|
|
101
117
|
if ([components.host isEqualToString:@"mmsdk"]) {
|
|
102
118
|
// Handle MetaMask deep link return
|
|
103
|
-
|
|
119
|
+
Class metaMaskSDKClass = NSClassFromString(@"MetaMaskSDK");
|
|
120
|
+
id sharedInstance = [metaMaskSDKClass respondsToSelector:@selector(sharedInstance)]
|
|
121
|
+
? [metaMaskSDKClass performSelector:@selector(sharedInstance)]
|
|
122
|
+
: nil;
|
|
123
|
+
if (sharedInstance && [sharedInstance respondsToSelector:@selector(handleUrl:)]) {
|
|
124
|
+
[sharedInstance performSelector:@selector(handleUrl:) withObject:url];
|
|
125
|
+
}
|
|
104
126
|
return YES;
|
|
105
127
|
}
|
|
106
128
|
|
|
@@ -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.8",
|
|
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,85 @@
|
|
|
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('replaces stale Swift import even if handler already exists', () => {
|
|
9
|
+
const config = {
|
|
10
|
+
modResults: {
|
|
11
|
+
language: 'swift',
|
|
12
|
+
contents: `import UIKit
|
|
13
|
+
import metamask_ios_sdk
|
|
14
|
+
|
|
15
|
+
class AppDelegate: NSObject {
|
|
16
|
+
func application(
|
|
17
|
+
_ app: UIApplication,
|
|
18
|
+
open url: URL,
|
|
19
|
+
options: [UIApplication.OpenURLOptionsKey: Any] = [:]
|
|
20
|
+
) -> Bool {
|
|
21
|
+
MetaMaskSDK.sharedInstance?.handleUrl(url)
|
|
22
|
+
return true
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
`,
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const result = withMetamaskAppDelegate(config)
|
|
30
|
+
const contents: string = result.modResults.contents
|
|
31
|
+
|
|
32
|
+
expect(contents).toContain('import NitroMetamask')
|
|
33
|
+
expect(contents).not.toContain('import metamask_ios_sdk')
|
|
34
|
+
expect((contents.match(/MetaMaskSDK\.sharedInstance\?\.handleUrl\(url\)/g) || []).length).toBe(1)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('injects NitroMetamask Swift import when missing', () => {
|
|
38
|
+
const config = {
|
|
39
|
+
modResults: {
|
|
40
|
+
language: 'swift',
|
|
41
|
+
contents: `import UIKit
|
|
42
|
+
|
|
43
|
+
class AppDelegate: NSObject {
|
|
44
|
+
}
|
|
45
|
+
`,
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const result = withMetamaskAppDelegate(config)
|
|
50
|
+
const contents: string = result.modResults.contents
|
|
51
|
+
|
|
52
|
+
expect(contents).toContain('import NitroMetamask')
|
|
53
|
+
expect(contents).toContain('MetaMaskSDK.sharedInstance?.handleUrl(url)')
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('migrates Objective-C direct SDK usage to runtime-safe calls', () => {
|
|
57
|
+
const config = {
|
|
58
|
+
modResults: {
|
|
59
|
+
language: 'objc',
|
|
60
|
+
contents: `#import "AppDelegate.h"
|
|
61
|
+
#import <MetaMaskSDK/MetaMaskSDK.h>
|
|
62
|
+
|
|
63
|
+
@implementation AppDelegate
|
|
64
|
+
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
|
|
65
|
+
NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:YES];
|
|
66
|
+
if ([components.host isEqualToString:@"mmsdk"]) {
|
|
67
|
+
[[MetaMaskSDK sharedInstance] handleUrl:url];
|
|
68
|
+
return YES;
|
|
69
|
+
}
|
|
70
|
+
return NO;
|
|
71
|
+
}
|
|
72
|
+
@end
|
|
73
|
+
`,
|
|
74
|
+
},
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const result = withMetamaskAppDelegate(config)
|
|
78
|
+
const contents: string = result.modResults.contents
|
|
79
|
+
|
|
80
|
+
expect(contents).not.toContain('#import <MetaMaskSDK/MetaMaskSDK.h>')
|
|
81
|
+
expect(contents).toContain('NSClassFromString(@"MetaMaskSDK")')
|
|
82
|
+
expect(contents).toContain('[sharedInstance performSelector:@selector(handleUrl:) withObject:url]')
|
|
83
|
+
expect(contents).not.toContain('[[MetaMaskSDK sharedInstance] handleUrl:url];')
|
|
84
|
+
})
|
|
85
|
+
})
|