From a9fb37ba4f954ef5239053d04954e606b78cd9c0 Mon Sep 17 00:00:00 2001 From: akaster99 Date: Thu, 4 Jan 2024 15:09:14 +0900 Subject: [PATCH 01/19] blockchainFilter --- src/ainize.ts | 1 + src/internal.ts | 23 +++--------------- src/middlewares/middleware.ts | 44 +++++++++++++--------------------- src/utils/extractor.ts | 45 +++++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 48 deletions(-) create mode 100644 src/utils/extractor.ts diff --git a/src/ainize.ts b/src/ainize.ts index 4bfc00f..5b739b3 100644 --- a/src/ainize.ts +++ b/src/ainize.ts @@ -83,6 +83,7 @@ export default class Ainize { if (!serviceUrl) { serviceUrl = `https://${serviceName}.ainetwork.xyz`; } + serviceUrl = serviceUrl.replace(/\/$/, ''); const servicePath = Path.app(serviceName).status(); await this.handler.subscribe(servicePath, resolve); await this.appController.createApp({ appName: serviceName, serviceUrl, billingConfig }); diff --git a/src/internal.ts b/src/internal.ts index cd96ea0..57b676e 100644 --- a/src/internal.ts +++ b/src/internal.ts @@ -4,6 +4,7 @@ import { getChangeBalanceOp, getResponseOp, getWriteHistoryOp } from "./utils/op import { HISTORY_TYPE, RESPONSE_STATUS, deposit, request, response } from "./types/type"; import { buildTxBody } from "./utils/builder"; import AinModule from "./ain"; +import { extractDataFromDepositRequest, extractDataFromServiceRequest } from "./utils/extractor"; export default class Internal { private ain = AinModule.getInstance(); @@ -35,28 +36,10 @@ export default class Internal { } getDataFromServiceRequest(req: Request) { - if(!req.body.valuePath[1] || !req.body.valuePath[3] || !req.body.valuePath[4] || !req.body.value) { - throw new Error("Not from service request"); - } - const requestData: request = { - appName: req.body.valuePath[1], - requesterAddress: req.body.auth.addr, - requestKey: req.body.valuePath[4], - requestData: req.body.value, - } - return requestData; + return extractDataFromServiceRequest(req); } private getDataFromDepositRequest(req: Request) { - if(!req.body.valuePath[1] || !req.body.valuePath[4] || !req.body.value) { - throw new Error("Not from deposit request"); - } - const depositData: deposit = { - transferKey: req.body.valuePath[4], - transferValue: req.body.value, - appName: req.body.valuePath[1], - requesterAddress: req.body.auth.addr, - } - return depositData; + return extractDataFromDepositRequest(req); } } \ No newline at end of file diff --git a/src/middlewares/middleware.ts b/src/middlewares/middleware.ts index e619353..f096085 100644 --- a/src/middlewares/middleware.ts +++ b/src/middlewares/middleware.ts @@ -1,51 +1,39 @@ import { Request, Response, NextFunction } from "express"; import NodeCache = require("node-cache"); +import { extractTriggerDataFromRequest } from "../utils/extractor"; +import AinModule from "../ain"; +import _ from "lodash"; export default class Middleware { cache: NodeCache; - constructor(cache: NodeCache,) { + private ain = AinModule.getInstance(); + constructor(cache: NodeCache) { this.cache = cache; } /** * Middleware for AI Network trigger call. It will filter duplicated request triggered by same transaction. - * It will pass request which is not from AI Network trigger. + * It will reject requests which is not from AI Network trigger. * @param {Request} request - Request data * @param {Res} response - Response data * @param {NextFunction} next - Next function * @returns Null if if request is duplicated. */ - triggerDuplicateFilter = (req: Request, res: Response, next: NextFunction) => { - if (req.body.transaction.hash === undefined){ - next(); - } - const txHash = req.body.transaction.hash; + blockchainTriggerFilter = async (req: Request, res: Response, next: NextFunction) => { + //check if request is from blockchain trigger + const { triggerPath, triggerValue, txHash } = extractTriggerDataFromRequest(req); + const result = await this.ain.getValue(triggerPath); + // if request is first reque st, set cache if (this.cache.get(txHash) && this.cache.get(txHash) !== "error") { res.send("duplicated"); return; } - // if request is first request, set cache this.cache.set(txHash, "in_progress", 500); - next(); + _.isEqual(result, triggerValue) ? res.send("not from blockChain") : next(); } - /** - * Middleware for AI Network trigger call. It will filter duplicated request triggered by same transaction. - * It will pass request which is not from AI Network trigger. - * You can set filter inside specific api. - * @param {Request} request - Request data - * @param {Res} response - Response data - * @returns Null if if request is duplicated. + /** + * DEPRECATED + * use blockchainTriggerFilter instead */ - triggerFilter = (req: Request, res: Response) => { - if (req.body.fid || req.body.transaction){ - res.send("not from trigger"); - return; - } - const txHash = req.body.transaction.hash; - if (this.cache.get(txHash) && this.cache.get(txHash) !== "error") { - res.send("duplicated"); - return; - } - this.cache.set(txHash, "in_progress", 500); - } + triggerDuplicateFilter = this.blockchainTriggerFilter; } \ No newline at end of file diff --git a/src/utils/extractor.ts b/src/utils/extractor.ts new file mode 100644 index 0000000..47be1f4 --- /dev/null +++ b/src/utils/extractor.ts @@ -0,0 +1,45 @@ +import { Request } from "express"; +import { deposit, request } from "../types/type"; + +export const extractDataFromServiceRequest = (req:Request) => { + if(!req.body.valuePath[1] || !req.body.valuePath[3] || !req.body.valuePath[4] || !req.body.value) { + throw new Error("Not from service request"); + } + const requestData: request = { + appName: req.body.valuePath[1], + requesterAddress: req.body.auth.addr, + requestKey: req.body.valuePath[4], + requestData: req.body.value, + } + return requestData; +} + +export const extractTriggerDataFromRequest = (req:Request) => { + if(req?.body?.valuePath === undefined) { + throw new Error("Not from trigger request"); + } + let path = ''; + req.body.valuePath.forEach((value:string) => { + path += value + '/'; + } + ); + const triggerData = { + triggerPath: path, + triggerValue: req.body.value, + txHash: req.body.txhash, + } + return triggerData +} + +export const extractDataFromDepositRequest = (req:Request) => { + if(!req.body.valuePath[1] || !req.body.valuePath[4] || !req.body.value) { + throw new Error("Not from deposit request"); + } + const depositData: deposit = { + transferKey: req.body.valuePath[4], + transferValue: req.body.value, + appName: req.body.valuePath[1], + requesterAddress: req.body.auth.addr, + } + return depositData; +} \ No newline at end of file From 1383ce3720dc924cff32d171ce6316a4461aafea Mon Sep 17 00:00:00 2001 From: akaster99 Date: Thu, 4 Jan 2024 15:36:14 +0900 Subject: [PATCH 02/19] fix: add await --- src/controllers/serviceController.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/serviceController.ts b/src/controllers/serviceController.ts index f5bbfbe..302c1ce 100644 --- a/src/controllers/serviceController.ts +++ b/src/controllers/serviceController.ts @@ -48,7 +48,7 @@ export default class ServiceController { } async chargeCredit(serviceName: string, amount: number): Promise { - this.checkRunning(serviceName); + await this.checkRunning(serviceName); const transferKey = Date.now(); const userAddress = this.ain.getAddress(); const depositAddress = await this.getDepositAddress(serviceName); @@ -78,7 +78,7 @@ export default class ServiceController { } async request(serviceName: string, requestData: any) : Promise { - this.checkRunning(serviceName); + await this.checkRunning(serviceName); const result = await new Promise(async (resolve, reject) => { const requestKey = Date.now(); const requesterAddress = this.ain.getAddress(); From eef0e3dfaa72866110efc520bac15b84dd6d8174 Mon Sep 17 00:00:00 2001 From: Yoojin Ko Date: Fri, 12 Jan 2024 11:44:25 +0900 Subject: [PATCH 03/19] feat: add signer functions --- src/ain.ts | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/ain.ts b/src/ain.ts index c271369..1928df4 100644 --- a/src/ain.ts +++ b/src/ain.ts @@ -2,6 +2,7 @@ import Ain from "@ainblockchain/ain-js"; import { getBlockChainEndpoint } from "./constants"; import { TransactionBody } from "@ainblockchain/ain-util"; import { txResult } from "./types/type"; +import { Signer } from "@ainblockchain/ain-js/lib/signer/signer"; // NOTE(yoojin): Plz suggest a good name. export default class AinModule { @@ -39,19 +40,29 @@ export default class AinModule { this.ain!.wallet.addAndSetDefaultAccount(privateKey); } + setSigner(signer: Signer) { + this.checkAinInitiated(); + this.ain!.setSigner(signer); + } + getDefaultAccount() { this.checkAinInitiated(); return this.ain!.wallet.defaultAccount; } - removeDefaultAccount() { + getSigner() { this.checkAinInitiated(); - this.ain!.wallet.removeDefaultAccount(); + return this.ain!.signer } getAddress() { - this.isDefaultAccountExist(); - return this.ain!.wallet.defaultAccount!.address; + this.checkAinInitiated(); + return this.getSigner().getAddress(); + } + + removeDefaultAccount() { + this.checkAinInitiated(); + this.ain!.wallet.removeDefaultAccount(); } async getBalance() { @@ -64,14 +75,14 @@ export default class AinModule { return await this.ain!.db.ref(path).getValue(); } - private async _sendTransaction(data: TransactionBody) { + private async _sendTransaction(txBody: TransactionBody) { this.checkAinInitiated(); - return await this.ain!.sendTransaction(data); + return await this.ain!.signer.sendTransaction(txBody); } private checkAinInitiated(): boolean { if (!this.ain) - throw new Error('Set initAin(chainId) First.'); + throw new Error('Set initAin(chainId) First.'); return true; } From a23bea6111c331e5835ad8b5db9eea11a68686d6 Mon Sep 17 00:00:00 2001 From: Yoojin Ko Date: Fri, 12 Jan 2024 11:44:35 +0900 Subject: [PATCH 04/19] chore: update ain-js --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 60f1021..2fee9e7 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "typescript": "^4.6.3" }, "dependencies": { - "@ainblockchain/ain-js": "^1.3.5", + "@ainblockchain/ain-js": "^1.6.3", "axios": "^0.26.1", "express": "^4.18.2", "fast-json-stable-stringify": "^2.1.0", diff --git a/yarn.lock b/yarn.lock index 414e102..f3d2629 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@ainblockchain/ain-js@^1.3.5": - version "1.6.0" - resolved "https://registry.npmjs.org/@ainblockchain/ain-js/-/ain-js-1.6.0.tgz" - integrity sha512-REzTJAf8w2TIsJLH7DhKWJF+kxfgMnCCwzWaeD4rYAv4TeD70PhFmYDrDMuy/qZd5KKMXqMigiU9PLWbiu8a7A== +"@ainblockchain/ain-js@^1.6.3": + version "1.6.3" + resolved "https://registry.yarnpkg.com/@ainblockchain/ain-js/-/ain-js-1.6.3.tgz#56ca744a6bf5e558f2acba75f106e8f88f5426ba" + integrity sha512-rdQfT6jcqcF4VP1twwMQkCijZ6SN1RewTjU1D35rJ7ZnRQjoIxekkodkdcIDVvyUEpR6A6iuT9SSSTz9KUMNbA== dependencies: "@ainblockchain/ain-util" "^1.1.9" "@types/node" "^12.7.3" From 64576fa934a35e8fe2ef12e97b6942cea847af0f Mon Sep 17 00:00:00 2001 From: Yoojin Ko Date: Fri, 12 Jan 2024 11:44:44 +0900 Subject: [PATCH 05/19] feat: add signer login --- src/ainize.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/ainize.ts b/src/ainize.ts index 4bfc00f..31f4400 100644 --- a/src/ainize.ts +++ b/src/ainize.ts @@ -8,6 +8,7 @@ import { deployConfig } from "./types/type"; import AinModule from "./ain"; import Internal from "./internal"; import { Account } from "@ainblockchain/ain-util"; +import { AinWalletSigner } from "@ainblockchain/ain-js/lib/signer/ain-wallet-signer"; export default class Ainize { private cache: NodeCache; @@ -42,6 +43,15 @@ export default class Ainize { console.log('login success! address:', this.ain.getAddress()); } + /** + * Login to ainize using AIN Wallet Signer. + */ + async loginWithSigner() { + const signer = new AinWalletSigner; + this.ain.setSigner(signer); + console.log('login success! address: ', this.ain.getAddress()); + } + /** * Logout from ainize. */ From dc326dcf3c2122971ef73c4446934c0fcbe4a192 Mon Sep 17 00:00:00 2001 From: Yoojin Ko Date: Fri, 12 Jan 2024 11:45:07 +0900 Subject: [PATCH 06/19] refactor: checkLoggedIn --- src/controllers/serviceController.ts | 11 +++++++---- src/service.ts | 14 +++++++------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/controllers/serviceController.ts b/src/controllers/serviceController.ts index 7f636b1..7f65b6d 100644 --- a/src/controllers/serviceController.ts +++ b/src/controllers/serviceController.ts @@ -120,13 +120,16 @@ export default class ServiceController { return (await this.ain.getValue(Path.app(serviceName).billingConfig())).depositAddress; } - isLoggedIn(): void { - if(!this.ain.getDefaultAccount()) - throw new Error('You should login First.'); + checkLoggedIn(): void { + try { + !this.ain.getAddress(); + } catch(error) { + throw new Error('You should login first.'); + } } async isAdmin(serviceName: string): Promise { - this.isLoggedIn(); + this.checkLoggedIn(); const adminPath = `/manage_app/${serviceName}/config/admin`; const adminList = await this.ain.getValue(adminPath); if(!adminList[this.ain.getAddress()]) { diff --git a/src/service.ts b/src/service.ts index 5f94786..8e7524c 100644 --- a/src/service.ts +++ b/src/service.ts @@ -42,7 +42,7 @@ export default class Service { * @returns {string} Transaction hash. */ async chargeCredit(amount: number) { - this.isLoggedIn(); + this.checkLoggedIn(); return await this.serviceController.chargeCredit(this.serviceName, amount); } @@ -52,7 +52,7 @@ export default class Service { * @returns {string} Transaction hash. */ async withdrawCredit(amount: number) { - this.isLoggedIn(); + this.checkLoggedIn(); return await this.serviceController.withdrawCredit(this.serviceName, amount); } @@ -61,7 +61,7 @@ export default class Service { * @returns {number} Amount of credit balance. */ async getCreditBalance() { - this.isLoggedIn(); + this.checkLoggedIn(); return await this.serviceController.getCreditBalance(this.serviceName); } @@ -70,7 +70,7 @@ export default class Service { * @returns {creditHistories} Histories of credit deposit and usage. */ async getCreditHistory() { - this.isLoggedIn(); + this.checkLoggedIn(); return await this.serviceController.getCreditHistory(this.serviceName); } @@ -80,7 +80,7 @@ export default class Service { * @returns {string} Response data from service. */ async request(requestData: any, requestKey?: string) { - this.isLoggedIn(); + this.checkLoggedIn(); return await this.serviceController.request(this.serviceName, requestData, requestKey); } @@ -113,7 +113,7 @@ export default class Service { return this.serviceController.isAdmin(this.serviceName); } - private isLoggedIn() { - return this.serviceController.isLoggedIn(); + private checkLoggedIn() { + return this.serviceController.checkLoggedIn(); } } From d1566ac69021ea4e1b019bbd39fd8ed588d77ed8 Mon Sep 17 00:00:00 2001 From: Yoojin Ko Date: Fri, 12 Jan 2024 15:31:40 +0900 Subject: [PATCH 07/19] feat: add signer logout --- src/ain.ts | 10 ++++++++++ src/ainize.ts | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/ain.ts b/src/ain.ts index 1928df4..9044401 100644 --- a/src/ain.ts +++ b/src/ain.ts @@ -3,6 +3,7 @@ import { getBlockChainEndpoint } from "./constants"; import { TransactionBody } from "@ainblockchain/ain-util"; import { txResult } from "./types/type"; import { Signer } from "@ainblockchain/ain-js/lib/signer/signer"; +import { DefaultSigner } from "@ainblockchain/ain-js/lib/signer/default-signer" // NOTE(yoojin): Plz suggest a good name. export default class AinModule { @@ -65,6 +66,15 @@ export default class AinModule { this.ain!.wallet.removeDefaultAccount(); } + removeSigner() { + this.checkAinInitiated(); + const wallet = this.ain!.wallet; + const provider = this.ain!.provider; + wallet.removeDefaultAccount(); + this.ain!.setSigner(new DefaultSigner(wallet, provider)) + } + + async getBalance() { this.isDefaultAccountExist(); return await this.ain!.wallet.getBalance(); diff --git a/src/ainize.ts b/src/ainize.ts index 31f4400..7e2950b 100644 --- a/src/ainize.ts +++ b/src/ainize.ts @@ -56,7 +56,7 @@ export default class Ainize { * Logout from ainize. */ async logout() { - this.ain.removeDefaultAccount(); + this.ain.removeSigner(); await this.handler.disconnect(); console.log('logout success!'); } From 850695787293ede0cba140129d4f6aa5dd605cbe Mon Sep 17 00:00:00 2001 From: akaster99 Date: Mon, 22 Jan 2024 13:54:01 +0900 Subject: [PATCH 08/19] fix: if --- src/middlewares/middleware.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/middlewares/middleware.ts b/src/middlewares/middleware.ts index f096085..f954533 100644 --- a/src/middlewares/middleware.ts +++ b/src/middlewares/middleware.ts @@ -29,7 +29,7 @@ export default class Middleware { return; } this.cache.set(txHash, "in_progress", 500); - _.isEqual(result, triggerValue) ? res.send("not from blockChain") : next(); + _.isEqual(result, triggerValue) ? next(): res.send("not from blockChain"); } /** * DEPRECATED From 569d173ee7acab65c21129c471ba5f13e8fe5626 Mon Sep 17 00:00:00 2001 From: Yoojin Ko Date: Tue, 23 Jan 2024 15:47:23 +0900 Subject: [PATCH 09/19] refactor: check logged in --- src/ain.ts | 19 ++++++++----------- src/ainize.ts | 23 +++++++++++++++++------ 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/ain.ts b/src/ain.ts index 9044401..aadf681 100644 --- a/src/ain.ts +++ b/src/ain.ts @@ -22,12 +22,6 @@ export default class AinModule { this.ain = new Ain(blockchainEndpoint, chainId); } - isDefaultAccountExist(): boolean { - if (this.getDefaultAccount()) - return true; - return false; - } - createAccount() { this.checkAinInitiated(); const newAccount = this.ain!.wallet.create(1)[0]; @@ -58,7 +52,11 @@ export default class AinModule { getAddress() { this.checkAinInitiated(); - return this.getSigner().getAddress(); + try { + return this.getSigner().getAddress(); + } catch (e) { + return null; + } } removeDefaultAccount() { @@ -74,10 +72,9 @@ export default class AinModule { this.ain!.setSigner(new DefaultSigner(wallet, provider)) } - async getBalance() { - this.isDefaultAccountExist(); - return await this.ain!.wallet.getBalance(); + const address = this.getAddress(); + return address ? await this.ain!.wallet.getBalance(address) : null; } async getValue(path: string) { @@ -92,7 +89,7 @@ export default class AinModule { private checkAinInitiated(): boolean { if (!this.ain) - throw new Error('Set initAin(chainId) First.'); + throw new Error('Set initAin(chainId) first.'); return true; } diff --git a/src/ainize.ts b/src/ainize.ts index 7e2950b..4d113d7 100644 --- a/src/ainize.ts +++ b/src/ainize.ts @@ -61,12 +61,25 @@ export default class Ainize { console.log('logout success!'); } + /** + * Throw error if user doesn't log in. + * @returns {} + */ + async checkLoggedIn() { + const address = await this.ain.getAddress(); + if (!address) { + throw new Error('You should login first.'); + } + } + async getAddress(): Promise { - return await this.ain.getAddress(); + await this.checkLoggedIn(); + return await this.ain.getAddress()!; } async getAinBalance(): Promise { - return await this.ain.getBalance(); + await this.checkLoggedIn(); + return await this.ain.getBalance() || 0; } // FIXME(yoojin): add config type and change param type. @@ -77,12 +90,10 @@ export default class Ainize { */ // TODO(yoojin, woojae): Deploy container, advanced. async deploy({serviceName, billingConfig, serviceUrl}: deployConfig): Promise { - if(!this.ain.isDefaultAccountExist()) { - throw new Error('you should login first'); - } + await this.checkLoggedIn(); // TODO(yoojin, woojae): Add container deploy logic. const result = await new Promise(async (resolve, reject) => { - const deployer = this.ain.getAddress(); + const deployer = this.ain.getAddress()!; if (!billingConfig) { billingConfig = { ...DEFAULT_BILLING_CONFIG, From 56967579477456103d1c00d9115fbf9775699b81 Mon Sep 17 00:00:00 2001 From: Yoojin Ko Date: Thu, 25 Jan 2024 13:43:37 +0900 Subject: [PATCH 10/19] fix: await getAddress --- src/ainize.ts | 22 ++++------------------ src/controllers/appController.ts | 2 +- src/controllers/serviceController.ts | 17 ++++++++--------- src/handlers/handler.ts | 2 +- 4 files changed, 14 insertions(+), 29 deletions(-) diff --git a/src/ainize.ts b/src/ainize.ts index 4d113d7..3d9f9f8 100644 --- a/src/ainize.ts +++ b/src/ainize.ts @@ -40,7 +40,7 @@ export default class Ainize { async login(privateKey: string) { this.ain.setDefaultAccount(privateKey); await this.handler.connect(); - console.log('login success! address:', this.ain.getAddress()); + console.log('login success! address:', await this.ain.getAddress()); } /** @@ -49,7 +49,7 @@ export default class Ainize { async loginWithSigner() { const signer = new AinWalletSigner; this.ain.setSigner(signer); - console.log('login success! address: ', this.ain.getAddress()); + console.log('login success! address: ', await this.ain.getAddress()); } /** @@ -61,24 +61,11 @@ export default class Ainize { console.log('logout success!'); } - /** - * Throw error if user doesn't log in. - * @returns {} - */ - async checkLoggedIn() { - const address = await this.ain.getAddress(); - if (!address) { - throw new Error('You should login first.'); - } - } - async getAddress(): Promise { - await this.checkLoggedIn(); - return await this.ain.getAddress()!; + return await this.ain.getAddress(); } async getAinBalance(): Promise { - await this.checkLoggedIn(); return await this.ain.getBalance() || 0; } @@ -90,10 +77,9 @@ export default class Ainize { */ // TODO(yoojin, woojae): Deploy container, advanced. async deploy({serviceName, billingConfig, serviceUrl}: deployConfig): Promise { - await this.checkLoggedIn(); // TODO(yoojin, woojae): Add container deploy logic. const result = await new Promise(async (resolve, reject) => { - const deployer = this.ain.getAddress()!; + const deployer = await this.ain.getAddress(); if (!billingConfig) { billingConfig = { ...DEFAULT_BILLING_CONFIG, diff --git a/src/controllers/appController.ts b/src/controllers/appController.ts index 21899f6..09b1114 100644 --- a/src/controllers/appController.ts +++ b/src/controllers/appController.ts @@ -124,7 +124,7 @@ export default class AppController { } async checkCostAndBalance(appName: string, value: string) { - const requesterAddress = this.ain.getAddress(); + const requesterAddress = await this.ain.getAddress(); const billingConfig = (await this.getBillingConfig(appName)); const token = value.split(' ').length; let cost = token * billingConfig.costPerToken; diff --git a/src/controllers/serviceController.ts b/src/controllers/serviceController.ts index 7f65b6d..cd7ff83 100644 --- a/src/controllers/serviceController.ts +++ b/src/controllers/serviceController.ts @@ -50,7 +50,7 @@ export default class ServiceController { async chargeCredit(serviceName: string, amount: number): Promise { this.checkRunning(serviceName); const transferKey = Date.now(); - const userAddress = this.ain.getAddress(); + const userAddress = await this.ain.getAddress(); const depositAddress = await this.getDepositAddress(serviceName); const op_list: SetOperation[] = [ getTransferOp(userAddress, depositAddress, transferKey.toString(), amount), @@ -66,13 +66,14 @@ export default class ServiceController { } async getCreditBalance(serviceName: string): Promise { - const userAddress = this.ain.getAddress(); + const userAddress = await this.ain.getAddress(); + console.log("userAddress in getCreditBalance", userAddress) const balancePath = Path.app(serviceName).balanceOfUser(userAddress); return await this.ain.getValue(balancePath) as number | 0; } async getCreditHistory(serviceName: string): Promise { - const userAddress = this.ain.getAddress(); + const userAddress = await this.ain.getAddress(); const creditHistoryPath = Path.app(serviceName).historyOfUser(userAddress); return await this.ain.getValue(creditHistoryPath) as creditHistories; } @@ -82,7 +83,7 @@ export default class ServiceController { const result = await new Promise(async (resolve, reject) => { requestKey = requestKey || Date.now().toString(); try { - const requesterAddress = this.ain.getAddress(); + const requesterAddress = await this.ain.getAddress(); const responsePath = Path.app(serviceName).response(requesterAddress, requestKey.toString()); await this.handler.subscribe(responsePath, resolve); const requestPath = Path.app(serviceName).request(requesterAddress, requestKey); @@ -121,9 +122,7 @@ export default class ServiceController { } checkLoggedIn(): void { - try { - !this.ain.getAddress(); - } catch(error) { + if (!this.ain.isAccountSetUp()) { throw new Error('You should login first.'); } } @@ -132,8 +131,8 @@ export default class ServiceController { this.checkLoggedIn(); const adminPath = `/manage_app/${serviceName}/config/admin`; const adminList = await this.ain.getValue(adminPath); - if(!adminList[this.ain.getAddress()]) { - throw new Error('You are not admin'); + if(!adminList[(await this.ain.getAddress())]) { + throw new Error('You are not a service admin.'); } } } \ No newline at end of file diff --git a/src/handlers/handler.ts b/src/handlers/handler.ts index d82c7c5..f6aeae7 100644 --- a/src/handlers/handler.ts +++ b/src/handlers/handler.ts @@ -32,7 +32,7 @@ export default class Handler { } private async disconnectedCb() { - if(AinModule.getInstance().isDefaultAccountExist()) { + if(await AinModule.getInstance().getAddress()) { console.log('disconnected. reconnecting...'); await this.connect(); } From 788d88562123f510a4e3df44cb0629866b531650 Mon Sep 17 00:00:00 2001 From: Yoojin Ko Date: Thu, 25 Jan 2024 13:44:22 +0900 Subject: [PATCH 11/19] fix: add isAccountSetUp and check signer tx --- src/ain.ts | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/ain.ts b/src/ain.ts index aadf681..8b6c3fc 100644 --- a/src/ain.ts +++ b/src/ain.ts @@ -50,12 +50,22 @@ export default class AinModule { return this.ain!.signer } - getAddress() { + async getAddress() { this.checkAinInitiated(); try { return this.getSigner().getAddress(); } catch (e) { - return null; + throw new Error("Need to set up an account or signer first."); + } + } + + isAccountSetUp() { + try { + this.checkAinInitiated(); + this.getSigner().getAddress(); + return true; + } catch (e) { + return false; } } @@ -73,8 +83,9 @@ export default class AinModule { } async getBalance() { - const address = this.getAddress(); - return address ? await this.ain!.wallet.getBalance(address) : null; + const address = await this.getAddress(); + const balancePath = `/accounts/${address}/balance`; + return await this.ain!.db.ref(balancePath).getValue(); } async getValue(path: string) { @@ -110,6 +121,13 @@ export default class AinModule { private handleTxResultWrapper(operation: Function) { return async (args: any) => { const res = await operation(args); + // ainWalletSigner return txHash or undefined. + if (typeof res === 'string') { + return res; + } else if (res === undefined) { + throw new Error(`Failed to build transaction.`); + } + // defaultSigner return a result object of transactions. const { tx_hash, result } = res; if (this.hasFailedOpResultList(result)) { throw new Error( From b99da6e729d0227f6675c026ec219614c722f570 Mon Sep 17 00:00:00 2001 From: Yoojin Ko Date: Fri, 26 Jan 2024 11:12:38 +0900 Subject: [PATCH 12/19] fix: subscribe data --- src/handlers/handler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/handlers/handler.ts b/src/handlers/handler.ts index f6aeae7..230bdf5 100644 --- a/src/handlers/handler.ts +++ b/src/handlers/handler.ts @@ -49,7 +49,7 @@ export default class Handler { }, (valueChangedEvent: any) => { this.unsubscribe(subscribeId); - resolve(valueChangedEvent.values.after.data); + resolve(valueChangedEvent.values.after); }, (err) => { throw new Error(err.message); From ba53f43c860b34a0ab1c7dce54f6c09a38b41449 Mon Sep 17 00:00:00 2001 From: akaster99 Date: Tue, 30 Jan 2024 14:00:27 +0900 Subject: [PATCH 13/19] fix: path --- src/middlewares/middleware.ts | 4 ++++ src/utils/extractor.ts | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/middlewares/middleware.ts b/src/middlewares/middleware.ts index f954533..02b5975 100644 --- a/src/middlewares/middleware.ts +++ b/src/middlewares/middleware.ts @@ -22,6 +22,10 @@ export default class Middleware { blockchainTriggerFilter = async (req: Request, res: Response, next: NextFunction) => { //check if request is from blockchain trigger const { triggerPath, triggerValue, txHash } = extractTriggerDataFromRequest(req); + if(!triggerPath || !triggerValue || !txHash) { + res.send("not from blockChain"); + return; + } const result = await this.ain.getValue(triggerPath); // if request is first reque st, set cache if (this.cache.get(txHash) && this.cache.get(txHash) !== "error") { diff --git a/src/utils/extractor.ts b/src/utils/extractor.ts index 47be1f4..87c7686 100644 --- a/src/utils/extractor.ts +++ b/src/utils/extractor.ts @@ -26,7 +26,7 @@ export const extractTriggerDataFromRequest = (req:Request) => { const triggerData = { triggerPath: path, triggerValue: req.body.value, - txHash: req.body.txhash, + txHash: req.body.transaction.hash, } return triggerData } From 2aaa4dbd87a0ee9534ad265bc886134b85c56262 Mon Sep 17 00:00:00 2001 From: akaster99 Date: Tue, 30 Jan 2024 14:03:52 +0900 Subject: [PATCH 14/19] letterCase --- src/middlewares/middleware.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/middlewares/middleware.ts b/src/middlewares/middleware.ts index 02b5975..49139d5 100644 --- a/src/middlewares/middleware.ts +++ b/src/middlewares/middleware.ts @@ -23,17 +23,17 @@ export default class Middleware { //check if request is from blockchain trigger const { triggerPath, triggerValue, txHash } = extractTriggerDataFromRequest(req); if(!triggerPath || !triggerValue || !txHash) { - res.send("not from blockChain"); + res.send("Not from blockChain"); return; } const result = await this.ain.getValue(triggerPath); // if request is first reque st, set cache if (this.cache.get(txHash) && this.cache.get(txHash) !== "error") { - res.send("duplicated"); + res.send("Duplicated"); return; } this.cache.set(txHash, "in_progress", 500); - _.isEqual(result, triggerValue) ? next(): res.send("not from blockChain"); + _.isEqual(result, triggerValue) ? next(): res.send("Not from blockChain"); } /** * DEPRECATED From dc4d34a5b40a21722dbd11ad31430d7cd86cbba8 Mon Sep 17 00:00:00 2001 From: akaster99 Date: Tue, 30 Jan 2024 14:04:29 +0900 Subject: [PATCH 15/19] fix --- src/middlewares/middleware.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/middlewares/middleware.ts b/src/middlewares/middleware.ts index 49139d5..1b36249 100644 --- a/src/middlewares/middleware.ts +++ b/src/middlewares/middleware.ts @@ -23,7 +23,7 @@ export default class Middleware { //check if request is from blockchain trigger const { triggerPath, triggerValue, txHash } = extractTriggerDataFromRequest(req); if(!triggerPath || !triggerValue || !txHash) { - res.send("Not from blockChain"); + res.send("Not from blockchain"); return; } const result = await this.ain.getValue(triggerPath); @@ -33,7 +33,7 @@ export default class Middleware { return; } this.cache.set(txHash, "in_progress", 500); - _.isEqual(result, triggerValue) ? next(): res.send("Not from blockChain"); + _.isEqual(result, triggerValue) ? next(): res.send("Not from blockchain"); } /** * DEPRECATED From 9c69c1233a7f48f53191d40abb3410ba0c32f1b3 Mon Sep 17 00:00:00 2001 From: yoojinko Date: Tue, 30 Jan 2024 05:45:53 +0000 Subject: [PATCH 16/19] Upgrade version to 1.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2fee9e7..e4064d8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ainize-team/ainize-js", - "version": "1.0.6", + "version": "1.1.0", "main": "dist/ainize.js", "types": "dist/ainize.d.ts", "scripts": { From ad595e89c68af95375cc315ac3798999941bdfca Mon Sep 17 00:00:00 2001 From: Yoojin Ko Date: Tue, 30 Jan 2024 15:30:57 +0900 Subject: [PATCH 17/19] fix: remove log --- src/controllers/serviceController.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/controllers/serviceController.ts b/src/controllers/serviceController.ts index 9093cca..c08889d 100644 --- a/src/controllers/serviceController.ts +++ b/src/controllers/serviceController.ts @@ -67,7 +67,6 @@ export default class ServiceController { async getCreditBalance(serviceName: string): Promise { const userAddress = await this.ain.getAddress(); - console.log("userAddress in getCreditBalance", userAddress) const balancePath = Path.app(serviceName).balanceOfUser(userAddress); return await this.ain.getValue(balancePath) as number | 0; } From 5ba3fdc5a1afd6af4646c8d00e9ee3dd2ce5af87 Mon Sep 17 00:00:00 2001 From: Yoojin Ko Date: Tue, 30 Jan 2024 17:23:11 +0900 Subject: [PATCH 18/19] docs: readme --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 8373db3..f8cca66 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,12 @@ You should login to ainize with AI Network account before deploy the container. ainize.login(); ``` +You can also login using [AIN Wallet](https://chromewebstore.google.com/detail/ain-wallet/hbdheoebpgogdkagfojahleegjfkhkpl) on the web. +```typescript +ainize.loginWithSigner(); +``` +This feature is supported from AIN Wallet version 2.1.0 or later. + ### Deploy You can deploy your AI service to ainize. ```typescript From 786969ebba752ae296f2a206e5526cd3b5e79a43 Mon Sep 17 00:00:00 2001 From: Yoojin Ko Date: Wed, 31 Jan 2024 11:49:52 +0900 Subject: [PATCH 19/19] docs: readme wallet ver --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f8cca66..55ca756 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ You can also login using [AIN Wallet](https://chromewebstore.google.com/detail/a ```typescript ainize.loginWithSigner(); ``` -This feature is supported from AIN Wallet version 2.1.0 or later. +This feature is supported from AIN Wallet version 2.0.5 or later. ### Deploy You can deploy your AI service to ainize.