@@ -189,8 +189,14 @@ export class Engine extends IEngine {
189189 optionalNamespaces : params . optionalNamespaces || { } ,
190190 } ;
191191 await this . isValidConnect ( connectParams ) ;
192- const { pairingTopic, requiredNamespaces, optionalNamespaces, sessionProperties, relays } =
193- connectParams ;
192+ const {
193+ pairingTopic,
194+ requiredNamespaces,
195+ optionalNamespaces,
196+ sessionProperties,
197+ scopedProperties,
198+ relays,
199+ } = connectParams ;
194200 let topic = pairingTopic ;
195201 let uri : string | undefined ;
196202 let active = false ;
@@ -232,6 +238,7 @@ export class Engine extends IEngine {
232238 expiryTimestamp,
233239 pairingTopic : topic ,
234240 ...( sessionProperties && { sessionProperties } ) ,
241+ ...( scopedProperties && { scopedProperties } ) ,
235242 id : payloadId ( ) ,
236243 } ;
237244 const sessionConnectTarget = engineEvent ( "session_connect" , proposal . id ) ;
@@ -317,7 +324,8 @@ export class Engine extends IEngine {
317324 throw error ;
318325 }
319326
320- const { id, relayProtocol, namespaces, sessionProperties, sessionConfig } = params ;
327+ const { id, relayProtocol, namespaces, sessionProperties, scopedProperties, sessionConfig } =
328+ params ;
321329
322330 const proposal = this . client . proposal . get ( id ) ;
323331
@@ -353,6 +361,7 @@ export class Engine extends IEngine {
353361 controller : { publicKey : selfPublicKey , metadata : this . client . metadata } ,
354362 expiry : calcExpiry ( SESSION_EXPIRY ) ,
355363 ...( sessionProperties && { sessionProperties } ) ,
364+ ...( scopedProperties && { scopedProperties } ) ,
356365 ...( sessionConfig && { sessionConfig } ) ,
357366 } ;
358367 const transportType = TRANSPORT_TYPES . relay ;
@@ -1919,8 +1928,15 @@ export class Engine extends IEngine {
19191928 const { id, params } = payload ;
19201929 try {
19211930 this . isValidSessionSettleRequest ( params ) ;
1922- const { relay, controller, expiry, namespaces, sessionProperties, sessionConfig } =
1923- payload . params ;
1931+ const {
1932+ relay,
1933+ controller,
1934+ expiry,
1935+ namespaces,
1936+ sessionProperties,
1937+ scopedProperties,
1938+ sessionConfig,
1939+ } = payload . params ;
19241940 const pendingSession = [ ...this . pendingSessions . values ( ) ] . find (
19251941 ( s ) => s . sessionTopic === topic ,
19261942 ) ;
@@ -1950,6 +1966,7 @@ export class Engine extends IEngine {
19501966 metadata : controller . metadata ,
19511967 } ,
19521968 ...( sessionProperties && { sessionProperties } ) ,
1969+ ...( scopedProperties && { scopedProperties } ) ,
19531970 ...( sessionConfig && { sessionConfig } ) ,
19541971 transportType : TRANSPORT_TYPES . relay ,
19551972 } ;
@@ -2454,11 +2471,13 @@ export class Engine extends IEngine {
24542471 payload : formatJsonRpcRequest (
24552472 "wc_sessionPropose" ,
24562473 {
2474+ ...proposal ,
24572475 requiredNamespaces : proposal . requiredNamespaces ,
24582476 optionalNamespaces : proposal . optionalNamespaces ,
24592477 relays : proposal . relays ,
24602478 proposer : proposal . proposer ,
24612479 sessionProperties : proposal . sessionProperties ,
2480+ scopedProperties : proposal . scopedProperties ,
24622481 } ,
24632482 proposal . id ,
24642483 ) ,
@@ -2570,8 +2589,14 @@ export class Engine extends IEngine {
25702589 ) ;
25712590 throw new Error ( message ) ;
25722591 }
2573- const { pairingTopic, requiredNamespaces, optionalNamespaces, sessionProperties, relays } =
2574- params ;
2592+ const {
2593+ pairingTopic,
2594+ requiredNamespaces,
2595+ optionalNamespaces,
2596+ sessionProperties,
2597+ scopedProperties,
2598+ relays,
2599+ } = params ;
25752600 if ( ! isUndefined ( pairingTopic ) ) await this . isValidPairingTopic ( pairingTopic ) ;
25762601
25772602 if ( ! isValidRelays ( relays , true ) ) {
@@ -2593,6 +2618,24 @@ export class Engine extends IEngine {
25932618 if ( ! isUndefined ( sessionProperties ) ) {
25942619 this . validateSessionProps ( sessionProperties , "sessionProperties" ) ;
25952620 }
2621+
2622+ if ( ! isUndefined ( scopedProperties ) ) {
2623+ this . validateSessionProps ( scopedProperties , "scopedProperties" ) ;
2624+
2625+ const requestedNamespaces = Object . keys ( requiredNamespaces || { } ) . concat (
2626+ Object . keys ( optionalNamespaces || { } ) ,
2627+ ) ;
2628+
2629+ const scopedNamespaces = Object . keys ( scopedProperties ) ;
2630+ const valid = scopedNamespaces . every ( ( ns ) => requestedNamespaces . includes ( ns ) ) ;
2631+ if ( ! valid ) {
2632+ throw new Error (
2633+ `Scoped properties must be a subset of required/optional namespaces, received: ${ JSON . stringify (
2634+ scopedProperties ,
2635+ ) } , required/optional namespaces: ${ JSON . stringify ( requestedNamespaces ) } `,
2636+ ) ;
2637+ }
2638+ }
25962639 } ;
25972640
25982641 private validateNamespaces = (
@@ -2608,7 +2651,7 @@ export class Engine extends IEngine {
26082651 throw new Error (
26092652 getInternalError ( "MISSING_OR_INVALID" , `approve() params: ${ params } ` ) . message ,
26102653 ) ;
2611- const { id, namespaces, relayProtocol, sessionProperties } = params ;
2654+ const { id, namespaces, relayProtocol, sessionProperties, scopedProperties } = params ;
26122655
26132656 this . checkRecentlyDeleted ( id ) ;
26142657 await this . isValidProposalId ( id ) ;
@@ -2632,6 +2675,23 @@ export class Engine extends IEngine {
26322675 if ( ! isUndefined ( sessionProperties ) ) {
26332676 this . validateSessionProps ( sessionProperties , "sessionProperties" ) ;
26342677 }
2678+
2679+ if ( ! isUndefined ( scopedProperties ) ) {
2680+ this . validateSessionProps ( scopedProperties , "scopedProperties" ) ;
2681+
2682+ const approvedNamespaces = new Set ( Object . keys ( namespaces ) ) ;
2683+ const scopedNamespaces = Object . keys ( scopedProperties ) ;
2684+
2685+ // the approved scoped namespaces must be a subset of the approved namespaces
2686+ const valid = scopedNamespaces . every ( ( ns ) => approvedNamespaces . has ( ns ) ) ;
2687+ if ( ! valid ) {
2688+ throw new Error (
2689+ `Scoped properties must be a subset of approved namespaces, received: ${ JSON . stringify (
2690+ scopedProperties ,
2691+ ) } , approved namespaces: ${ Array . from ( approvedNamespaces ) . join ( ", " ) } `,
2692+ ) ;
2693+ }
2694+ }
26352695 } ;
26362696
26372697 private isValidReject : EnginePrivate [ "isValidReject" ] = async ( params ) => {
@@ -2889,12 +2949,14 @@ export class Engine extends IEngine {
28892949 return context ;
28902950 } ;
28912951
2892- private validateSessionProps = ( properties : ProposalTypes . SessionProperties , type : string ) => {
2893- Object . values ( properties ) . forEach ( ( property ) => {
2894- if ( ! isValidString ( property , false ) ) {
2952+ private validateSessionProps = ( properties : SessionTypes . ScopedProperties , type : string ) => {
2953+ Object . values ( properties ) . forEach ( ( property , index ) => {
2954+ if ( property === null || property === undefined ) {
28952955 const { message } = getInternalError (
28962956 "MISSING_OR_INVALID" ,
2897- `${ type } must be in Record<string, string> format. Received: ${ JSON . stringify ( property ) } ` ,
2957+ `${ type } must contain an existing value for each key. Received: ${ property } for key ${
2958+ Object . keys ( properties ) [ index ]
2959+ } `,
28982960 ) ;
28992961 throw new Error ( message ) ;
29002962 }
0 commit comments