-
-
Notifications
You must be signed in to change notification settings - Fork 201
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Add Multichain API to @metamask/multichain
#4813
Changes from 218 commits
bc56104
a4b52ad
86ab58a
186d4b3
6a93d1d
231bcaa
4e52fc0
151eaac
85a723e
a0bb278
1cd8ef2
c636def
a6aa7c1
42134f7
a13b9c7
81db877
a3fc263
afe5cb9
9ea78be
5650d31
df5167e
9446b0b
f65ca24
941849d
a250de2
aa7ba39
8415be6
c7f510e
4afa8f8
597e837
1872188
c5d8005
54f7c49
ada451d
2322e39
9b21677
00a41cb
f30dd8b
71085a0
f2be8f0
644f4d0
1b78bbc
fc28c89
ba25ce5
4ceb118
a36ec4d
95dfbc9
9bcf869
633485c
609518a
afb2e2c
7c97afe
ba210ac
109a7bf
1e67641
32b213a
dae4f73
b673f62
d7ed999
b4b65e2
4d752b7
fad338d
5bf15a2
8208931
c5980c6
106e986
5c6bb8f
a7a8e6e
0962fb2
54829e0
6b367f0
42297f9
dc31704
56176d1
26acfcd
2e3bfb4
89d6101
b7ea5d5
7203358
046133a
eea9f46
257618a
67b222e
ead2f43
009fb4a
e34032b
0631c48
4685547
18d1112
1ba77c7
bb50a19
7d32a0b
f095370
62929a4
491552f
bd0f50f
41dcc83
d80c9ce
6eb3e87
8374f37
d6dfc71
0d167a3
17af395
62975b6
19a5983
439ef9b
7d61af6
b5d0cd7
97b4a09
6732cd9
e03033c
e1793ff
4c9be0e
a25c05d
b35bdc3
2ad05a3
79acd26
32aa807
121ba94
6d4bd04
3f4c297
5a621b3
aef155f
944be53
5f98801
b79f827
242629d
57e6ab5
0007fa5
1ec9503
02144d1
78737cb
f8ca898
e8b2487
9cfbf21
ca2b343
507093e
5f96567
40b7757
2a983d2
4542942
b6765a4
e6a3346
c0637f0
d8d90ce
c102e37
3d68f83
d997b82
a3e9d8f
7f11b8a
a551ba2
6f61047
f94c4f6
d1aad26
da3fb04
4a7ae5d
c54714f
840d27d
8874ebc
c344d3d
ff57ba3
dc0283e
b439461
e77e87f
5a2c8a0
3f65e22
1399f97
0fd56ce
bf4e136
5c79a54
7c4aa65
4ad37a9
c760400
43d1dcd
61c654a
c1dd11f
2c085fe
f550ee4
0353672
fa5b27f
cf554f8
298fc54
d07f372
b0b350f
1c0cc44
07d969c
e3def86
e05b7d3
10158bd
f371565
b57d706
6244b7b
93683d1
1a87b4d
96f372c
8f02d61
da7aed7
0cc5cc6
20588ef
e595d48
a32a95b
36449e9
8fff351
78f7775
24f17e0
13ad655
8c34b81
7d16401
cc369d6
3cb0fe7
718b553
4776860
d184228
6700c42
af0d8c7
237eb59
ab3ce47
2ba4557
7b09a5c
ac1abef
ee79d3e
310120e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
import { | ||
KnownNotifications, | ||
KnownRpcMethods, | ||
KnownWalletNamespaceRpcMethods, | ||
KnownWalletRpcMethods, | ||
} from '../scope/constants'; | ||
import { | ||
getInternalScopesObject, | ||
getSessionScopes, | ||
} from './caip-permission-adapter-session-scopes'; | ||
|
||
describe('CAIP-25 session scopes adapters', () => { | ||
describe('getInternalScopesObject', () => { | ||
it('returns an InternalScopesObject with only the accounts from each NormalizedScopeObject', () => { | ||
const result = getInternalScopesObject({ | ||
'wallet:eip155': { | ||
methods: ['foo', 'bar'], | ||
notifications: ['baz'], | ||
accounts: ['wallet:eip155:0xdead'], | ||
}, | ||
'eip155:1': { | ||
methods: ['eth_call'], | ||
notifications: ['eth_subscription'], | ||
accounts: ['eip155:1:0xdead', 'eip155:1:0xbeef'], | ||
}, | ||
}); | ||
|
||
expect(result).toStrictEqual({ | ||
'wallet:eip155': { | ||
accounts: ['wallet:eip155:0xdead'], | ||
}, | ||
'eip155:1': { | ||
accounts: ['eip155:1:0xdead', 'eip155:1:0xbeef'], | ||
}, | ||
}); | ||
}); | ||
}); | ||
|
||
describe('getSessionScopes', () => { | ||
it('returns a NormalizedScopesObject for the wallet scope', () => { | ||
const result = getSessionScopes({ | ||
requiredScopes: {}, | ||
optionalScopes: { | ||
wallet: { | ||
accounts: [], | ||
}, | ||
}, | ||
}); | ||
|
||
expect(result).toStrictEqual({ | ||
wallet: { | ||
methods: KnownWalletRpcMethods, | ||
notifications: [], | ||
accounts: [], | ||
}, | ||
}); | ||
}); | ||
|
||
it('returns a NormalizedScopesObject for the wallet:eip155 scope', () => { | ||
const result = getSessionScopes({ | ||
requiredScopes: {}, | ||
optionalScopes: { | ||
'wallet:eip155': { | ||
accounts: ['wallet:eip155:0xdeadbeef'], | ||
}, | ||
}, | ||
}); | ||
|
||
expect(result).toStrictEqual({ | ||
'wallet:eip155': { | ||
methods: KnownWalletNamespaceRpcMethods.eip155, | ||
notifications: [], | ||
accounts: ['wallet:eip155:0xdeadbeef'], | ||
}, | ||
}); | ||
}); | ||
|
||
it('returns a NormalizedScopesObject with empty methods and notifications for scope with wallet namespace and unknown reference', () => { | ||
const result = getSessionScopes({ | ||
requiredScopes: {}, | ||
optionalScopes: { | ||
'wallet:foobar': { | ||
accounts: ['wallet:foobar:0xdeadbeef'], | ||
}, | ||
}, | ||
}); | ||
|
||
expect(result).toStrictEqual({ | ||
'wallet:foobar': { | ||
methods: [], | ||
notifications: [], | ||
accounts: ['wallet:foobar:0xdeadbeef'], | ||
}, | ||
}); | ||
}); | ||
|
||
it('returns a NormalizedScopesObject with empty methods and notifications for scope not wallet namespace and unknown reference', () => { | ||
const result = getSessionScopes({ | ||
requiredScopes: {}, | ||
optionalScopes: { | ||
'foo:1': { | ||
accounts: ['foo:1:0xdeadbeef'], | ||
}, | ||
}, | ||
}); | ||
|
||
expect(result).toStrictEqual({ | ||
'foo:1': { | ||
methods: [], | ||
notifications: [], | ||
accounts: ['foo:1:0xdeadbeef'], | ||
}, | ||
}); | ||
}); | ||
|
||
it('returns a NormalizedScopesObject for a eip155 namespaced scope', () => { | ||
const result = getSessionScopes({ | ||
requiredScopes: {}, | ||
optionalScopes: { | ||
'eip155:1': { | ||
accounts: ['eip155:1:0xdeadbeef'], | ||
}, | ||
}, | ||
}); | ||
|
||
expect(result).toStrictEqual({ | ||
'eip155:1': { | ||
methods: KnownRpcMethods.eip155, | ||
notifications: KnownNotifications.eip155, | ||
accounts: ['eip155:1:0xdeadbeef'], | ||
}, | ||
}); | ||
}); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import { KnownCaipNamespace } from '@metamask/utils'; | ||
|
||
import type { Caip25CaveatValue } from '../caip25Permission'; | ||
import { | ||
KnownNotifications, | ||
KnownRpcMethods, | ||
KnownWalletNamespaceRpcMethods, | ||
KnownWalletRpcMethods, | ||
} from '../scope/constants'; | ||
import { mergeScopes } from '../scope/transform'; | ||
import type { | ||
InternalScopesObject, | ||
NonWalletKnownCaipNamespace, | ||
NormalizedScopesObject, | ||
} from '../scope/types'; | ||
import { parseScopeString } from '../scope/types'; | ||
|
||
/** | ||
* Converts an NormalizedScopesObject to a InternalScopesObject. | ||
* @param normalizedScopesObject - The NormalizedScopesObject to convert. | ||
* @returns An InternalScopesObject. | ||
*/ | ||
export const getInternalScopesObject = ( | ||
normalizedScopesObject: NormalizedScopesObject, | ||
) => { | ||
const internalScopes: InternalScopesObject = {}; | ||
|
||
Object.entries(normalizedScopesObject).forEach( | ||
([_scopeString, { accounts }]) => { | ||
const scopeString = _scopeString as keyof typeof normalizedScopesObject; | ||
|
||
internalScopes[scopeString] = { | ||
accounts, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wait, so we are throwing away all of the methods etc? What is the plan then if we want to do more granular permissioning down the line, then we will require another potentially tricky migration? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So we originally were including the methods in the serialized permission itself (and granularly enforcing each metho), but after discussions w/ @Gudahtt we realized that approach would
|
||
}; | ||
}, | ||
); | ||
|
||
return internalScopes; | ||
}; | ||
|
||
/** | ||
* Converts an InternalScopesObject to a NormalizedScopesObject. | ||
* @param internalScopesObject - The InternalScopesObject to convert. | ||
* @returns A NormalizedScopesObject. | ||
*/ | ||
const getNormalizedScopesObject = ( | ||
internalScopesObject: InternalScopesObject, | ||
) => { | ||
const normalizedScopes: NormalizedScopesObject = {}; | ||
|
||
Object.entries(internalScopesObject).forEach( | ||
([_scopeString, { accounts }]) => { | ||
const scopeString = _scopeString as keyof typeof internalScopesObject; | ||
const { namespace, reference } = parseScopeString(scopeString); | ||
let methods: string[] = []; | ||
let notifications: string[] = []; | ||
|
||
if (namespace === KnownCaipNamespace.Wallet) { | ||
if (reference) { | ||
methods = | ||
KnownWalletNamespaceRpcMethods[ | ||
reference as NonWalletKnownCaipNamespace | ||
] ?? []; | ||
} else { | ||
methods = KnownWalletRpcMethods; | ||
} | ||
} else { | ||
methods = | ||
KnownRpcMethods[namespace as NonWalletKnownCaipNamespace] ?? []; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems incompatible with non-EVM as well? 🤔 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. see #4813 (comment) |
||
notifications = | ||
KnownNotifications[namespace as NonWalletKnownCaipNamespace] ?? []; | ||
} | ||
|
||
normalizedScopes[scopeString] = { | ||
methods, | ||
notifications, | ||
accounts, | ||
}; | ||
}, | ||
); | ||
|
||
return normalizedScopes; | ||
}; | ||
|
||
/** | ||
* Takes the scopes from an endowment:caip25 permission caveat value, | ||
* hydrates them with supported methods and notifications, and returns a NormalizedScopesObject. | ||
* @param caip25CaveatValue - The CAIP-25 CaveatValue to convert. | ||
* @returns A NormalizedScopesObject. | ||
*/ | ||
export const getSessionScopes = ( | ||
caip25CaveatValue: Pick< | ||
Caip25CaveatValue, | ||
'requiredScopes' | 'optionalScopes' | ||
>, | ||
) => { | ||
return mergeScopes( | ||
getNormalizedScopesObject(caip25CaveatValue.requiredScopes), | ||
getNormalizedScopesObject(caip25CaveatValue.optionalScopes), | ||
); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is one of the few times I've seen the chain ID converted to a bigint instead of a BN!