diff --git a/README-2.md b/README-2.md
index 97fea1f07df0f3f0e20defa465312ef270fd4f4d..fbf3c87b17ea47fc546d5e3077c7da9cc4ee2ff5 100644
--- a/README-2.md
+++ b/README-2.md
@@ -1,4 +1,10 @@
-# Processus de mise-à-jour
+## Installation d'outils
+
+```sh
+pnpm install --global @subsquid/cli@latest
+```
+
+## Processus de mise-à-jour du runtime
 
 Pour mettre à jour les métadonnées du runtime
 
@@ -7,9 +13,20 @@ pnpm install --global @subsquid/substrate-metadata-explorer
 squid-substrate-metadata-explorer --rpc ws://127.0.0.1:9944 --out gdev-metadata.jsonl
 ```
 
+## Processus de mise-à-jour du réseau
+
 Pour mettre à jour les assets (nouveau réseau)
 
 ```sh
 # copier le lien depuis https://git.duniter.org/nodes/rust/duniter-v2s/-/releases/
 wget https://nodes.pages.duniter.org/-/rust/duniter-v2s/-/jobs/120948/artifacts/release/gdev.json -O ./assets/gdev.json
+```
+
+## Publication d'image docker
+
+Ce que je fais pour publier l'image
+
+```sh
+docker build . -t h30x/duniter-squid
+docker image push h30x/duniter-squid
 ```
\ No newline at end of file
diff --git a/src/main.ts b/src/main.ts
index b5c5add7086d2b558436e19703805d9354d2959a..f40fd0b9cf7dea0a5172520ca4685ada377b1e2d 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -50,7 +50,7 @@ processor.run(new TypeormDatabaseWithCache(), async (ctx) => {
   getNewData(ctx, ndata);
 
   // transform new data to objects
-  let prepared: PreparedData = {
+  let data: Data = {
     accounts: new Map(),
     identities: new Map(),
     changeOwnerKey: [],
@@ -60,10 +60,10 @@ processor.run(new TypeormDatabaseWithCache(), async (ctx) => {
     certRenewal: [],
     certRemoval: [],
   };
-  await prepareData(ctx, ndata, prepared);
+  await prepareData(ctx, ndata, data);
 
   // store data
-  await storeData(ctx, prepared);
+  await storeData(ctx, data);
 });
 
 // =====================================================================================================
@@ -72,6 +72,7 @@ processor.run(new TypeormDatabaseWithCache(), async (ctx) => {
 export type Address = string;
 export type IdtyIndex = number;
 type BlockNumber = number;
+type Ctx = ProcessorContext<StoreWithCache>;
 
 // a way to group data returned from events
 // this contains partial data to be turned into types
@@ -117,7 +118,7 @@ interface CertRemovalEvent {
 interface IdtyCreatedEvent {
   id: string;
   index: IdtyIndex;
-  account: Address;
+  accountId: Address;
 }
 interface IdtyConfirmedEvent {
   id: string;
@@ -127,12 +128,12 @@ interface IdtyConfirmedEvent {
 interface IdtyChangedOwnerKeyEvent {
   id: string;
   index: IdtyIndex;
-  account: Address;
+  accountId: Address;
   blockNumber: BlockNumber;
 }
 
 // a way to group data prepared for database insertion
-interface PreparedData {
+interface Data {
   accounts: Map<Address, Account>;
   identities: Map<IdtyIndex, Identity>;
   changeOwnerKey: ChangeOwnerKey[];
@@ -146,7 +147,7 @@ interface PreparedData {
 // ================================================================================
 
 /// fill data with data collected from events
-function getNewData(ctx: ProcessorContext<StoreWithCache>, ndata: NewData) {
+function getNewData(ctx: Ctx, ndata: NewData) {
   const silence_events = [
     events_t.system.extrinsicSuccess.name,
     events_t.system.killedAccount.name,
@@ -213,7 +214,7 @@ function getNewData(ctx: ProcessorContext<StoreWithCache>, ndata: NewData) {
           ndata.identitiesCreated.push({
             id: event.id,
             index: newI.idtyIndex,
-            account: ss58.codec(42).encode(newI.ownerKey),
+            accountId: ss58.codec(42).encode(newI.ownerKey),
           });
           break;
 
@@ -243,7 +244,7 @@ function getNewData(ctx: ProcessorContext<StoreWithCache>, ndata: NewData) {
           ndata.idtyChangedOwnerKey.push({
             id: event.id,
             index: chok.idtyIndex,
-            account: ss58.codec(42).encode(chok.newOwnerKey),
+            accountId: ss58.codec(42).encode(chok.newOwnerKey),
             blockNumber: block.header.height,
           });
           break;
@@ -315,7 +316,7 @@ function getNewData(ctx: ProcessorContext<StoreWithCache>, ndata: NewData) {
 // =============================================================================================================
 
 /// prepare data for injection into database
-async function prepareData(ctx: ProcessorContext<StoreWithCache>, newData: NewData, data: PreparedData) {
+async function prepareData(ctx: Ctx, newData: NewData, data: Data) {
   await createAccounts(ctx, newData, data);
   await createIdentities(ctx, newData, data);
   await confirmIdentities(ctx, newData, data);
@@ -329,7 +330,7 @@ async function prepareData(ctx: ProcessorContext<StoreWithCache>, newData: NewDa
 // =============================================
 
 /// store prepared data into database
-async function storeData(ctx: ProcessorContext<StoreWithCache>, data: PreparedData) {
+async function storeData(ctx: Ctx, data: Data) {
   // UPSERT = update or insert if not existing
   // account can have already existed, been killed, and recreated
   await ctx.store.upsert([...data.accounts.values()]);
@@ -348,7 +349,7 @@ async function storeData(ctx: ProcessorContext<StoreWithCache>, data: PreparedDa
 
 // =============================================================================================================
 
-async function createAccounts(ctx: ProcessorContext<StoreWithCache>, newData: NewData, data: PreparedData) {
+async function createAccounts(ctx: Ctx, newData: NewData, data: Data) {
   // system will tell when accounts are created (but this should be added above)
   for (let id of newData.accounts) {
     let newA = new Account({ id });
@@ -357,9 +358,20 @@ async function createAccounts(ctx: ProcessorContext<StoreWithCache>, newData: Ne
   }
 }
 
-async function createIdentities(ctx: ProcessorContext<StoreWithCache>, newData: NewData, data: PreparedData) {
+async function getOrCreateAccount(ctx: Ctx, data: Data, id: Address): Promise<Account> {
+  let account = data.accounts.get(id) ?? await ctx.store.get(Account, id);
+  if (account == null) {
+    // we need to create it
+    account = new Account({id});
+    data.accounts.set(id, account);
+  }
+  return account;
+}
+
+async function createIdentities(ctx: Ctx, newData: NewData, data: Data) {
   for (let i of newData.identitiesCreated) {
-    let account = await ctx.store.getOrFail(Account, i.account);
+    // an identity can be created for a non existing account without System.NewAccount event
+    let account = await getOrCreateAccount(ctx, data, i.accountId);
     let newI = new Identity({
       id: i.id,
       index: i.index,
@@ -370,19 +382,22 @@ async function createIdentities(ctx: ProcessorContext<StoreWithCache>, newData:
   }
 }
 
-async function confirmIdentities(ctx: ProcessorContext<StoreWithCache>, newData: NewData, data: PreparedData) {
+async function confirmIdentities(ctx: Ctx, newData: NewData, data: Data) {
   for (let i of newData.identitiesConfirmed) {
-    let idty = await ctx.store.findOneByOrFail(Identity, { index: i.index });
+    // should never fail because identities can not be confirmed without have been created
+    let idty = data.identities.get(i.index) ?? await ctx.store.findOneByOrFail(Identity, { index: i.index });
     idty.name = i.name;
     data.identities.set(i.index, idty);
   }
 }
 
-async function changeIdtyOwnerKey(ctx: ProcessorContext<StoreWithCache>, newData: NewData, data: PreparedData) {
+async function changeIdtyOwnerKey(ctx: Ctx, newData: NewData, data: Data) {
   for (let icok of newData.idtyChangedOwnerKey) {
+    // should never fail because change owner key is only available for existing identites
     let idty = await ctx.store.findOneOrFail(Identity, { where: { index: icok.index }, relations: { account: true } });
+    // should never fail because old_account must pay fees to call change owner key
     let old_account = data.accounts.get(idty.account.id) ?? (await ctx.store.getOrFail(Account, idty.account.id));
-    let new_account = data.accounts.get(icok.account) ?? (await ctx.store.getOrFail(Account, icok.account));
+    let new_account = await getOrCreateAccount(ctx, data, icok.accountId);
     ctx.log.info(`changed owner key of idty ${idty.index} from ${old_account.id} to ${new_account.id}`);
     // actually change the account of the identity
     idty.account = new_account;
@@ -400,10 +415,12 @@ async function changeIdtyOwnerKey(ctx: ProcessorContext<StoreWithCache>, newData
   }
 }
 
-async function createTransfers(ctx: ProcessorContext<StoreWithCache>, newData: NewData, data: PreparedData) {
+async function createTransfers(ctx: Ctx, newData: NewData, data: Data) {
   for (let t of newData.transfers) {
     let { id, blockNumber, timestamp, amount } = t;
+    // should never fail because source of transfer must be an existing account
     let from = data.accounts.get(t.from) ?? (await ctx.store.getOrFail(Account, t.from));
+    // shoud never fail because destination of transfer must be existing account or raise System.NewAccount
     let to = data.accounts.get(t.to) ?? (await ctx.store.getOrFail(Account, t.to));
     data.transfers.push(
       new Transfer({
@@ -418,15 +435,16 @@ async function createTransfers(ctx: ProcessorContext<StoreWithCache>, newData: N
   }
 }
 
-async function createCerts(ctx: ProcessorContext<StoreWithCache>, newData: NewData, data: PreparedData) {
+async function createCerts(ctx: Ctx, newData: NewData, data: Data) {
   for (let c of newData.certCreation) {
     let { id, issuerId, receiverId, createdOn, expireOn } = c;
     let cert = await ctx.store.findOne(Cert, {
       relations: { issuer: true, receiver: true },
       where: { issuer: { index: issuerId }, receiver: { index: receiverId } },
     });
+    // first creation of the cert
     if (cert == null) {
-      // this is the first creation of the cert
+      // should never fail because cert issuer and receiver must be existing or created identities
       let issuer = data.identities.get(issuerId) ?? (await ctx.store.findOneByOrFail(Identity, { index: issuerId }));
       let receiver = data.identities.get(receiverId) ?? (await ctx.store.findOneByOrFail(Identity, { index: receiverId }));
       cert = new Cert({
@@ -437,9 +455,10 @@ async function createCerts(ctx: ProcessorContext<StoreWithCache>, newData: NewDa
         createdOn,
         expireOn,
       });
-    } else {
-      // the cert has already existed, expired, and is created again
-      // we update it
+    } 
+    // the cert has already existed, expired, and is created again
+    // we update it accordingly
+    else {
       cert.active = true;
       cert.createdOn = createdOn;
       cert.expireOn = expireOn;
@@ -456,9 +475,11 @@ async function createCerts(ctx: ProcessorContext<StoreWithCache>, newData: NewDa
   }
 }
 
-async function createCertRenewals(ctx: ProcessorContext<StoreWithCache>, newData: NewData, data: PreparedData) {
+async function createCertRenewals(ctx: Ctx, newData: NewData, data: Data) {
   for (let c of newData.certRenewal) {
     let { id, issuerId, receiverId, blockNumber, expireOn } = c;
+    // should never fail because cert renewal can only happen on existing cert
+    // and can not be renewed at the same block as created (delay)
     let cert = await ctx.store.findOneOrFail(Cert, {
       relations: { issuer: true, receiver: true },
       where: { issuer: { index: issuerId }, receiver: { index: receiverId } },
@@ -476,9 +497,11 @@ async function createCertRenewals(ctx: ProcessorContext<StoreWithCache>, newData
   }
 }
 
-async function createCertRemovals(ctx: ProcessorContext<StoreWithCache>, newData: NewData, data: PreparedData) {
+async function createCertRemovals(ctx: Ctx, newData: NewData, data: Data) {
   for (let c of newData.certRemoval) {
     let { id, issuerId, receiverId, blockNumber } = c;
+    // should never fail because cert removal can only happen on existing cert
+    // and cert should not be removed at their creation block
     let cert = await ctx.store.findOneOrFail(Cert, {
       relations: { issuer: true, receiver: true },
       where: { issuer: { index: issuerId }, receiver: { index: receiverId } },