> For the complete documentation index, see [llms.txt](https://unirep.gitbook.io/unirep/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://unirep.gitbook.io/unirep/getting-started/start-with-typescript/7.-user-state-transition.md).

# 7. User state transition

See how to generate a user state: [4. Epoch key proof](/unirep/getting-started/start-with-typescript/4.-epoch-key-proof.md).\
Then use the user state to generate user state transition proofs.

```typescript
const {
    startTransitionProof,
    processAttestationProofs,
    finalTransitionProof,
} = await userState.genUserStateTransitionProofs()
```

### Submit start transition proof

```typescript
const tx = await contract.startUserStateTransition(
    startTransitionProof.publicSignals,
    startTransitionProof.proof
)
```

Get the proof index of `startTransitionProof`

```typescript
const proofIndexes: ethers.BigNumber[] = []
await tx.wait() // should wait until the transaction is confirmed
const proofHash = startTransitionProof.hash()
const proofIndex = await contract.getProofIndex(proofHash)
proofIndexes.push(proofIndex)
```

### Submit process attestations proofs

Submit all process attestations proofs and get the proof indexes.

```typescript
for (let i = 0; i < processAttestationProofs.length; i++) {
    const tx = await contract.processAttestations(
        processAttestationProofs[i].publicSignals,
        processAttestationProofs[i].proof
    )
    await tx.wait() // wait until the transaction is confirmed
    
    const proofHash = processAttestationProofs[i].hash()
    const proofIndex = await contract.getProofIndex(proofHash)
    proofIndexes.push(proofIndex)
}
```

### Submit user state transition proof

```typescript
const tx = await contract.updateUserStateRoot(
    finalTransitionProof.publicSignals,
    finalTransitionProof.proof,
    proofIndexes
)
```

### Verify UniRep state

It can be checked with either a `Synchronizer` object or a `UserState` object. See: [4. Epoch Key Proof](https://unirep.gitbook.io/unirep/getting-started/start-with-typescript/pages/1JerVmkBWmXopgmm9GsN#9.-verify-unirep-state).

Check if global state tree root exists in the current UniRep state

```typescript
const fromEpoch = Number(finalTransitionProof.transitionFromEpoch)
const GSTRoot = finalTransitionProof.fromGlobalStateTree.toString()
const isGSTRootExisted = await userState.GSTRootExists(
    GSTRoot, 
    fromEpoch
)
console.log(isGSTRootExisted) // false then the proof will be invalid 
```

Check if epoch tree root matches the epoch

```typescript
const fromEpoch = Number(finalTransitionProof.transitionFromEpoch)
const epochTreeRoot = finalTransitionProof.fromEpochTree.toString()
const isEpochTreeExisted = await userState.epochTreeRootExists(
    epochTreeRoot, 
    fromEpoch
)
console.log(isEpochTreeExisted) // false then the proof will be invalid
```

Check epoch key nullifiers are not existed

```typescript
const epkNullifiers = finalTransitionProof.epkNullifiers.map((i) => i.toString())
for (const nullifier of epkNullifiers) {
    if (await userState.nullifierExist(nullifier)) {
        return false // then the proof will be invalid
    }
}
```
