diff --git a/apps/indexer-coordinator/package.json b/apps/indexer-coordinator/package.json
index 03168872..9f2bcceb 100644
--- a/apps/indexer-coordinator/package.json
+++ b/apps/indexer-coordinator/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@subql/indexer-coordinator",
-  "version": "2.5.0",
+  "version": "2.6.0",
   "description": "",
   "author": "SubQuery",
   "license": "Apache-2.0",
@@ -45,7 +45,7 @@
     "@nestjs/schedule": "^2.2.2",
     "@nestjs/serve-static": "^2.2.2",
     "@nestjs/typeorm": "8.1.4",
-    "@subql/contract-sdk": "1.3.0",
+    "@subql/contract-sdk": "1.3.1-0",
     "@subql/network-clients": "1.1.0",
     "@subql/network-config": "1.1.1",
     "@subql/network-query": "1.1.1",
diff --git a/apps/indexer-coordinator/src/payg/payg.resolver.ts b/apps/indexer-coordinator/src/payg/payg.resolver.ts
index d182452f..21658619 100644
--- a/apps/indexer-coordinator/src/payg/payg.resolver.ts
+++ b/apps/indexer-coordinator/src/payg/payg.resolver.ts
@@ -43,9 +43,11 @@ export class PaygResolver {
   channelExtend(
     @Args('id') id: string,
     @Args('expiration') expiration: number,
-    @Args('price', { nullable: true }) price?: string
+    @Args('price', { nullable: true }) price?: string,
+    @Args('indexerSign', { nullable: true }) indexerSign?: string,
+    @Args('consumerSign', { nullable: true }) consumerSign?: string
   ) {
-    return this.paygService.extend(id, expiration, price);
+    return this.paygService.extend(id, expiration, price, indexerSign, consumerSign);
   }
 
   @Mutation(() => ChannelType)
diff --git a/apps/indexer-coordinator/src/payg/payg.service.ts b/apps/indexer-coordinator/src/payg/payg.service.ts
index 0fff6242..9ddc112b 100644
--- a/apps/indexer-coordinator/src/payg/payg.service.ts
+++ b/apps/indexer-coordinator/src/payg/payg.service.ts
@@ -389,14 +389,30 @@ export class PaygService implements OnModuleInit {
     }
   }
 
-  async extend(id: string, expiration: number, price?: string): Promise<Channel> {
+  async extend(
+    id: string,
+    expiration: number,
+    price?: string,
+    indexerSign?: string,
+    consumerSign?: string
+  ): Promise<Channel> {
     const channel = await this.channel(id);
     if (!channel) {
       throw new Error(`channel not exist: ${id}`);
     }
 
+    if (channel.status !== ChannelStatus.OPEN) {
+      throw new Error(`channel not open: ${id}`);
+    }
+
+    if (!indexerSign || !consumerSign) {
+      logger.debug(`extend channel requires indexerSign and consumerSign: ${id}`);
+      // throw new Error(`require indexerSign and consumerSign: ${id}`);
+    }
+
     let modified = false;
 
+    const preExpirationAt = channel.expiredAt;
     if (channel.expiredAt < expiration) {
       channel.expiredAt = expiration;
       modified = true;
@@ -408,12 +424,56 @@ export class PaygService implements OnModuleInit {
       modified = true;
     }
 
+    let signed = false;
+    if (indexerSign && consumerSign) {
+      // channel.lastConsumerSign = consumerSign;
+      // channel.lastIndexerSign = indexerSign;
+      modified = true;
+      signed = true;
+    }
+
     if (!modified) {
       return channel;
     }
 
-    logger.debug(`Extend state channel ${id}`);
+    const expr = expiration - preExpirationAt;
+
+    logger.debug(
+      `Extend state channel ${id}. ${JSON.stringify(
+        channel
+      )} preExpirationAt:${preExpirationAt} expr:${expr}`
+    );
 
+    if (signed) {
+      await this.contract.sendTransaction({
+        action: `state channel extend ${id}`,
+        type: TxType.check,
+        txFun: (overrides) =>
+          this.contract
+            .getSdk()
+            .stateChannel.extend(
+              id,
+              preExpirationAt,
+              expr,
+              indexerSign,
+              consumerSign,
+              channel.price,
+              overrides
+            ),
+        gasFun: (overrides) =>
+          this.contract
+            .getSdk()
+            .stateChannel.estimateGas.extend(
+              id,
+              preExpirationAt,
+              expr,
+              indexerSign,
+              consumerSign,
+              channel.price,
+              overrides
+            ),
+      });
+    }
     return this.saveAndPublish(channel, PaygEvent.State);
   }
 
diff --git a/apps/indexer-coordinator/yarn.lock b/apps/indexer-coordinator/yarn.lock
index 9cc7ec07..e81e1d41 100644
--- a/apps/indexer-coordinator/yarn.lock
+++ b/apps/indexer-coordinator/yarn.lock
@@ -1673,10 +1673,10 @@
   resolved "https://registry.yarnpkg.com/@sqltools/formatter/-/formatter-1.2.5.tgz#3abc203c79b8c3e90fd6c156a0c62d5403520e12"
   integrity sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==
 
-"@subql/contract-sdk@1.3.0":
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/@subql/contract-sdk/-/contract-sdk-1.3.0.tgz#e6474369a2156fd3dfd50a84535d9a2894480198"
-  integrity sha512-vxd8xwtxDtNjv9WXYKx3pD12tdRDJJZ7Cm5yTtyH4piGcvLtJXehENxSBvCKvGtgpvzba8DiwDmbjIMYdomNzA==
+"@subql/contract-sdk@1.3.1-0":
+  version "1.3.1-0"
+  resolved "https://registry.yarnpkg.com/@subql/contract-sdk/-/contract-sdk-1.3.1-0.tgz#a4608fadaf1c7882d66f5764d1710c7e81026ec9"
+  integrity sha512-sdBA0eALPV3MuAamYTlD80TW/x+NTmDmS+nFocaMEivrmXimh8JsasnOmjs3p1DXqcqNlDCr2d++9ctSOr75dQ==
 
 "@subql/network-clients@1.1.0":
   version "1.1.0"
diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml
index a673b134..980175ba 100644
--- a/deploy/docker-compose.yml
+++ b/deploy/docker-compose.yml
@@ -18,7 +18,7 @@ services:
       retries: 5
 
   coordinator:
-    image: subquerynetwork/indexer-coordinator:v2.5.0
+    image: subquerynetwork/indexer-coordinator:v2.6.0
     container_name: indexer_coordinator
     restart: always
     ports:
@@ -76,7 +76,7 @@ services:
       test: ['CMD', 'redis-cli', '--raw', 'incr', 'ping']
 
   proxy:
-    image: subquerynetwork/indexer-proxy:v2.6.2
+    image: subquerynetwork/indexer-proxy:v2.7.0
     container_name: indexer_proxy
     restart: always
     ports: