# 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
    }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://unirep.gitbook.io/unirep/getting-started/start-with-typescript/7.-user-state-transition.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
