@@ -36,6 +36,7 @@ export type WalletStatus = {
3636 pendingUpdates : Array < { imageHash : Hex . Hex ; signature : SequenceSignature . RawSignature } >
3737 /** Pending migrations, fully encoded with signature */
3838 pendingMigrations : Array < State . Migration >
39+ version : number
3940 chainId ?: number
4041 counterFactual : {
4142 context : Context . KnownContext | Context . Context
@@ -125,9 +126,12 @@ export class Wallet {
125126 Config . evaluateConfigurationSafety ( configuration )
126127 }
127128
129+ const status = await this . getStatus ( )
130+ this . requireV3Wallet ( status )
131+
128132 const imageHash = Config . hashConfiguration ( configuration )
129133 const blankEnvelope = (
130- await Promise . all ( [ this . prepareBlankEnvelope ( 0 ) , this . stateProvider . saveConfiguration ( configuration ) ] )
134+ await Promise . all ( [ this . prepareBlankEnvelope ( 0 , status ) , this . stateProvider . saveConfiguration ( configuration ) ] )
131135 ) [ 0 ]
132136
133137 return {
@@ -272,8 +276,9 @@ export class Wallet {
272276
273277 // Get migrations
274278 const detectedContextVersion = Context . getVersionFromContext ( context )
279+ let version = detectedContextVersion
275280 if ( detectedContextVersion !== 3 ) {
276- // TODO Cater for v3 -> v3 migrations
281+ // TODO Cater for pending v3 -> v3 migrations
277282 const migration = await this . stateProvider . getMigration (
278283 this . address ,
279284 fromImageHash ,
@@ -290,6 +295,7 @@ export class Wallet {
290295 migrations . push ( migration )
291296 // We will perform the migration and update configurations from there.
292297 fromImageHash = Bytes . toHex ( Config . hashConfiguration ( migration . toConfig ) )
298+ version = migration . toVersion
293299 }
294300 }
295301
@@ -313,6 +319,7 @@ export class Wallet {
313319 imageHash,
314320 pendingUpdates : [ ...updates ] . reverse ( ) ,
315321 pendingMigrations : [ ...migrations ] ,
322+ version,
316323 chainId,
317324 onChainImageHash : onChainImageHash ! ,
318325 context,
@@ -326,6 +333,7 @@ export class Wallet {
326333 imageHash,
327334 pendingUpdates : [ ...updates ] . reverse ( ) ,
328335 pendingMigrations : [ ...migrations ] ,
336+ version,
329337 chainId,
330338 counterFactual : {
331339 context : counterFactualContext ,
@@ -396,6 +404,7 @@ export class Wallet {
396404 }
397405
398406 const [ chainId , status ] = await Promise . all ( [ provider . request ( { method : 'eth_chainId' } ) , this . getStatus ( provider ) ] )
407+ this . requireV3Wallet ( status , true )
399408
400409 // If entrypoint is address(0) then 4337 is not enabled in this wallet
401410 if ( ! status . context . capabilities ?. erc4337 ?. entrypoint ) {
@@ -449,7 +458,7 @@ export class Wallet {
449458 factory,
450459 factoryData,
451460 } ,
452- ...( await this . prepareBlankEnvelope ( Number ( chainId ) , provider ) ) ,
461+ ...( await this . prepareBlankEnvelope ( Number ( chainId ) , status ) ) ,
453462 }
454463 }
455464
@@ -514,10 +523,12 @@ export class Wallet {
514523 this . getNonce ( provider , space ) ,
515524 ] )
516525
517- // If the latest configuration does not match the onchain configuration
518- // then we bundle the update into the transaction envelope
526+ // If the latest configuration does not match the onchain configuration, we bundle the update into the transaction envelope
527+ // Same for pending migrations
528+ const status = await this . getStatus ( provider )
529+ this . requireV3Wallet ( status )
530+
519531 if ( ! options ?. noConfigUpdate ) {
520- const status = await this . getStatus ( provider )
521532 if ( status . imageHash !== status . onChainImageHash ) {
522533 calls . push ( {
523534 to : this . address ,
@@ -538,7 +549,7 @@ export class Wallet {
538549 nonce,
539550 calls,
540551 } ,
541- ...( await this . prepareBlankEnvelope ( Number ( chainId ) , provider ) ) ,
552+ ...( await this . prepareBlankEnvelope ( Number ( chainId ) , status ) ) ,
542553 }
543554 }
544555
@@ -624,8 +635,11 @@ export class Wallet {
624635 const messageSize = Hex . size ( hexMessage )
625636 encodedMessage = Hex . concat ( Hex . fromString ( `${ `\x19Ethereum Signed Message:\n${ messageSize } ` } ` ) , hexMessage )
626637 }
638+ const status = await this . getStatus ( )
639+ this . requireV3Wallet ( status , true )
640+
627641 return {
628- ...( await this . prepareBlankEnvelope ( chainId ) ) ,
642+ ...( await this . prepareBlankEnvelope ( chainId , status ) ) ,
629643 payload : Payload . fromMessage ( encodedMessage ) ,
630644 }
631645 }
@@ -635,9 +649,8 @@ export class Wallet {
635649 provider ?: Provider . Provider ,
636650 ) : Promise < Bytes . Bytes > {
637651 const status = await this . getStatus ( provider )
638- if ( status . pendingMigrations . length > 0 ) {
639- throw new Error ( 'execute pending migrations before signing a message' )
640- }
652+ this . requireV3Wallet ( status , true )
653+
641654 const signature = Envelope . encodeSignature ( envelope )
642655 if ( ! status . isDeployed ) {
643656 const deployTransaction = await this . buildDeployTransaction ( )
@@ -650,13 +663,21 @@ export class Wallet {
650663 return encoded
651664 }
652665
653- private async prepareBlankEnvelope ( chainId : number , provider ?: Provider . Provider ) {
654- const status = await this . getStatus ( provider )
655-
666+ private prepareBlankEnvelope ( chainId : number , status : WalletStatus ) {
656667 return {
657668 wallet : this . address ,
658669 chainId : chainId ,
659670 configuration : status . configuration ,
660671 }
661672 }
673+
674+ private requireV3Wallet ( status : WalletStatus , noPendingMigrations : boolean = false ) : boolean {
675+ if ( status . version !== 3 ) {
676+ throw new Error ( 'migrate to v3 before performing this action' )
677+ }
678+ if ( noPendingMigrations && status . pendingMigrations . length > 0 ) {
679+ throw new Error ( 'execute pending migrations before performing this action' )
680+ }
681+ return true
682+ }
662683}
0 commit comments